diff --git a/.github/workflows/merge_upstream_master.yml b/.github/workflows/merge_upstream_master.yml index 152bbf2ca06..372f144899d 100644 --- a/.github/workflows/merge_upstream_master.yml +++ b/.github/workflows/merge_upstream_master.yml @@ -113,7 +113,7 @@ jobs: - name: Rebuild TGUI run: | - if git diff-tree --name-only -r $(git rev-parse HEAD~2) | grep "tgui/public/" + if git diff-tree --name-only -r $(git rev-parse HEAD~2) | grep "tgui/public/" ; then bash tgui/bin/tgui git commit -m "Rebuild TGUI" git push origin diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index c472e55eb21..8a476cb63b6 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -404,8 +404,11 @@ CREATE TABLE `notes` ( `server` varchar(50) NOT NULL, `crew_playtime` mediumint(8) UNSIGNED DEFAULT '0', `automated` TINYINT(3) UNSIGNED NULL DEFAULT '0', + `deleted` TINYINT(4) NOT NULL DEFAULT '0', + `deletedby` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`id`), - KEY `ckey` (`ckey`) + KEY `ckey` (`ckey`), + KEY `deleted` (`deleted`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/SQL/updates/55-56.sql b/SQL/updates/55-56.sql new file mode 100644 index 00000000000..c6799413b38 --- /dev/null +++ b/SQL/updates/55-56.sql @@ -0,0 +1,7 @@ +# Updating DB from 55-56 ~AffectedArc07 +# Adds a new column to the notes table for tracking deleted notes +ALTER TABLE `notes` + ADD COLUMN `deleted` TINYINT NOT NULL DEFAULT 0 AFTER `automated`, + ADD COLUMN `deletedby` VARCHAR(32) NULL DEFAULT NULL AFTER `deleted`, + ADD INDEX `deleted` (`deleted`); + diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm new file mode 100644 index 00000000000..1b2c987bc85 --- /dev/null +++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm @@ -0,0 +1,1440 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"bm" = ( +/obj/effect/landmark/burnturf, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"bF" = ( +/obj/machinery/door/airlock/public, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"bK" = ( +/obj/machinery/economy/vending/snack, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"cl" = ( +/obj/effect/decal/cleanable/blood, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"dD" = ( +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"dS" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"en" = ( +/obj/effect/landmark/burnturf, +/obj/effect/spawner/random_spawners/dirt_maybe, +/obj/item/reagent_containers/hypospray/autoinjector{ + name = "emergency autoinjector"; + icon_state = "autoinjector0" + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"eo" = ( +/obj/structure/table_frame, +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"eG" = ( +/obj/effect/landmark/burnturf, +/obj/effect/decal/cleanable/glass, +/obj/item/stack/rods, +/obj/item/airlock_electronics, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"fU" = ( +/obj/structure/table_frame, +/obj/item/stack/sheet/metal, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"ge" = ( +/obj/effect/landmark/burnturf, +/obj/effect/decal/cleanable/blood, +/obj/item/cigbutt, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"gY" = ( +/obj/machinery/computer/nonfunctional{ + dir = 4 + }, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"hb" = ( +/obj/effect/spawner/random_spawners/blood_maybe, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"hK" = ( +/turf/simulated/floor/lava/mapping_lava, +/area/lavaland/surface/outdoors) +"hW" = ( +/obj/item/stack/sheet/metal, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"jU" = ( +/obj/item/stack/sheet/metal, +/obj/structure/closet/firecloset, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"kk" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"kv" = ( +/obj/effect/landmark/damageturf, +/obj/item/flashlight/flare, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"ma" = ( +/obj/structure/shuttle/engine/propulsion{ + dir = 4 + }, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"mA" = ( +/obj/effect/mob_spawn/human/corpse/skeleton, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"mN" = ( +/obj/effect/spawner/random_spawners/blood_maybe, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"ng" = ( +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"nG" = ( +/obj/machinery/door/airlock/public, +/turf/simulated/floor/mineral/titanium/airless, +/area/ruin/unpowered/misc_lavaruin) +"oD" = ( +/obj/effect/spawner/random_spawners/blood_maybe, +/obj/item/storage/briefcase{ + pixel_x = 3; + pixel_y = -5 + }, +/obj/item/storage/briefcase{ + pixel_y = 0; + pixel_x = -3 + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"oF" = ( +/obj/structure/largecrate, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"oV" = ( +/obj/effect/decal/cleanable/generic, +/obj/machinery/light/built, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"qG" = ( +/obj/effect/decal/cleanable/blood, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"rw" = ( +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"rx" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/mob/living/simple_animal/hostile/asteroid/hivelord/legion, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"sa" = ( +/obj/effect/landmark/damageturf, +/obj/effect/spawner/random_spawners/blood_maybe, +/obj/effect/decal/cleanable/molten_object, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"sf" = ( +/obj/structure/reagent_dispensers/watertank, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"sx" = ( +/obj/structure/bonfire, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"sJ" = ( +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"sY" = ( +/obj/machinery/light_construct{ + dir = 4 + }, +/obj/item/stack/cable_coil{ + amount = 1 + }, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"tp" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"tH" = ( +/obj/structure/shuttle/engine/heater{ + dir = 4 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"tN" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord/legion, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"uQ" = ( +/obj/effect/landmark/burnturf, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"vA" = ( +/obj/effect/spawner/random_spawners/oil_maybe, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/item/storage/briefcase{ + pixel_x = -2; + pixel_y = -4 + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"wf" = ( +/obj/item/stack/rods, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"wD" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"xc" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/effect/mob_spawn/human/corpse/skeleton, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"xd" = ( +/obj/item/stack/rods, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"xJ" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"yo" = ( +/obj/machinery/light/built{ + dir = 4 + }, +/obj/item/light/tube{ + status = 2 + }, +/obj/effect/decal/cleanable/cobweb2, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"zo" = ( +/obj/machinery/door/airlock/public, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"zv" = ( +/obj/machinery/light/built, +/obj/item/light/tube{ + status = 2 + }, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"zG" = ( +/obj/structure/toilet{ + dir = 2 + }, +/turf/simulated/floor/mineral/titanium/airless, +/area/ruin/unpowered/misc_lavaruin) +"zM" = ( +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/structure/largecrate, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"zX" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/mapping_helpers/no_lava, +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"Aj" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"Ax" = ( +/obj/effect/spawner/random_spawners/blood_maybe, +/obj/structure/closet/crate/can, +/obj/item/paper/crumpled, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"AC" = ( +/obj/structure/sink{ + pixel_x = 12; + dir = 4 + }, +/obj/item/mounted/mirror{ + icon_state = "mirror_broke"; + pixel_y = -32 + }, +/turf/simulated/floor/mineral/titanium/airless, +/area/ruin/unpowered/misc_lavaruin) +"AO" = ( +/obj/machinery/economy/vending/cigarette, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Bf" = ( +/obj/structure/closet/firecloset, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"BX" = ( +/obj/effect/decal/cleanable/glass, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Ca" = ( +/obj/effect/landmark/burnturf, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Dt" = ( +/obj/effect/spawner/window/shuttle, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"DM" = ( +/obj/item/stack/rods/ten, +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"Et" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"Fy" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors) +"FO" = ( +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"FY" = ( +/obj/structure/table, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Gt" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"HF" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"HJ" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord/legion, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"It" = ( +/turf/simulated/wall/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"Iu" = ( +/obj/effect/mob_spawn/human/corpse/skeleton, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"IL" = ( +/obj/effect/spawner/random_spawners/blood_maybe, +/obj/structure/window/reinforced, +/obj/item/c_tube, +/obj/item/flashlight, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"IQ" = ( +/obj/item/stack/sheet/metal, +/obj/effect/spawner/random_spawners/dirt_maybe, +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Ks" = ( +/obj/effect/mob_spawn/human/corpse/skeleton, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Kx" = ( +/obj/effect/mob_spawn/human/corpse/skeleton, +/obj/effect/decal/cleanable/blood, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"KT" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/effect/mob_spawn/human/corpse/skeleton, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"LJ" = ( +/obj/structure/extinguisher_cabinet{ + pixel_y = -32 + }, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Mb" = ( +/obj/item/shard{ + icon_state = "medium"; + pixel_x = 3; + pixel_y = 7 + }, +/obj/item/shard{ + icon_state = "small"; + pixel_y = -6; + pixel_x = -7 + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Mf" = ( +/obj/effect/landmark/damageturf, +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"My" = ( +/obj/machinery/door/airlock/public, +/obj/effect/landmark/damageturf, +/obj/effect/spawner/random_spawners/oil_maybe, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"MC" = ( +/obj/machinery/economy/vending/wallmed{ + name = "Emergency NanoMed"; + pixel_y = 28 + }, +/obj/machinery/door/window/reinforced/normal{ + name = "Luggage Storage" + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"MS" = ( +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"NE" = ( +/obj/structure/table, +/obj/item/storage/toolbox/mechanical, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"NG" = ( +/turf/simulated/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors) +"Oe" = ( +/turf/simulated/wall/mineral/titanium/nodiagonal, +/area/ruin/unpowered/misc_lavaruin) +"Oq" = ( +/obj/effect/landmark/burnturf, +/obj/structure/reagent_dispensers/fueltank, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Oz" = ( +/obj/effect/landmark/damageturf, +/obj/structure/largecrate, +/obj/structure/window/reinforced, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"OT" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"QD" = ( +/obj/machinery/light{ + dir = 2; + brightness_color = "#FF3232"; + emergency_mode = 1; + fire_mode = 1 + }, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"RH" = ( +/obj/effect/decal/cleanable/blood, +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"RK" = ( +/obj/structure/shuttle/engine/propulsion{ + dir = 2 + }, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"RP" = ( +/obj/machinery/door/airlock/public, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/misc_lavaruin) +"Sd" = ( +/obj/effect/spawner/random_spawners/dirt_maybe, +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"SH" = ( +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"Tb" = ( +/obj/effect/landmark/burnturf, +/obj/effect/decal/cleanable/ash, +/obj/item/storage/box/survival, +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Tm" = ( +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Ts" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/effect/mob_spawn/human/corpse/skeleton, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"TU" = ( +/obj/machinery/light{ + dir = 1; + brightness_color = "#FF3232"; + emergency_mode = 1; + fire_mode = 1 + }, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Ua" = ( +/obj/structure/table/reinforced, +/obj/item/paper/crumpled, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/unpowered/misc_lavaruin) +"Uw" = ( +/obj/structure/closet/walllocker/emerglocker/north, +/obj/effect/decal/cleanable/cobweb, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"Uz" = ( +/obj/effect/landmark/burnturf, +/turf/simulated/floor/mineral/titanium/blue, +/area/ruin/unpowered/misc_lavaruin) +"UV" = ( +/obj/effect/landmark/burnturf, +/obj/item/stack/rods, +/obj/effect/spawner/random_spawners/dirt_maybe, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Vs" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord/legion, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"WF" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/molten_object/large, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"WI" = ( +/obj/item/stack/sheet/metal, +/obj/item/light/tube{ + status = 2 + }, +/turf/simulated/floor/mineral/titanium, +/area/ruin/unpowered/misc_lavaruin) +"Yf" = ( +/obj/effect/decal/cleanable/ash, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface{ + icon_state = "basalt_dug" + }, +/area/lavaland/surface/outdoors) +"Yg" = ( +/obj/effect/landmark/damageturf, +/turf/simulated/floor/plating, +/area/ruin/unpowered/misc_lavaruin) +"Yi" = ( +/obj/effect/decal/cleanable/ash, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) + +(1,1,1) = {" +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +"} +(2,1,1) = {" +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +NG +"} +(3,1,1) = {" +NG +NG +NG +NG +NG +NG +dD +Gt +Gt +dD +dD +dD +Gt +Gt +NG +NG +NG +NG +NG +"} +(4,1,1) = {" +NG +NG +NG +NG +NG +NG +dD +Gt +It +Dt +Dt +Dt +It +Gt +NG +NG +NG +NG +NG +"} +(5,1,1) = {" +NG +NG +NG +NG +NG +dD +dD +dD +It +gY +Ua +gY +It +dD +dD +NG +NG +NG +NG +"} +(6,1,1) = {" +NG +NG +NG +NG +NG +dD +dD +dD +Dt +dS +FO +KT +Dt +dD +dD +NG +NG +NG +NG +"} +(7,1,1) = {" +NG +NG +NG +NG +dD +dD +Gt +Gt +Dt +yo +Kx +sY +Dt +Gt +Gt +dD +NG +NG +NG +"} +(8,1,1) = {" +NG +NG +NG +NG +dD +Gt +Gt +It +It +It +zo +It +It +It +Gt +Gt +NG +NG +NG +"} +(9,1,1) = {" +NG +NG +NG +NG +dD +Gt +It +It +fU +Tm +rw +ng +FY +It +It +Gt +NG +NG +NG +"} +(10,1,1) = {" +NG +NG +NG +NG +dD +dD +It +TU +ng +ng +rw +ng +ng +zv +It +dD +dD +NG +NG +"} +(11,1,1) = {" +NG +NG +NG +NG +dD +Gt +Dt +kk +ng +kk +DM +kk +ng +Ts +Dt +dD +dD +NG +NG +"} +(12,1,1) = {" +NG +NG +NG +NG +dD +Gt +Dt +kk +Ks +kk +rw +kk +ng +Ts +Dt +dD +SH +NG +NG +"} +(13,1,1) = {" +NG +NG +NG +dD +Gt +Gt +Dt +kk +ng +Ts +Mf +IQ +ng +kk +Dt +dD +dD +dD +NG +"} +(14,1,1) = {" +NG +NG +Gt +Vs +Gt +Gt +Dt +ng +ng +Ts +Mf +Ts +ng +Ts +Dt +dD +dD +dD +NG +"} +(15,1,1) = {" +NG +NG +Vs +sx +Vs +xJ +OT +rx +MS +xc +Mf +kk +ng +kk +Dt +dD +It +dD +NG +"} +(16,1,1) = {" +Gt +Gt +Gt +Gt +Gt +zX +OT +tp +Sd +HF +sa +bm +Uz +kk +Dt +dD +dD +dD +Fy +"} +(17,1,1) = {" +NG +dD +dD +hK +dD +Gt +Gt +en +Ca +UV +uQ +bm +Uz +ge +Et +SH +dD +It +Gt +"} +(18,1,1) = {" +NG +dD +hK +hK +dD +It +Gt +Aj +Aj +Aj +Aj +hW +Aj +mN +Et +Gt +Gt +Gt +Gt +"} +(19,1,1) = {" +dD +hK +hK +hK +hK +dD +hK +qG +Aj +hW +hK +Iu +hK +Aj +hK +dD +hK +dD +Gt +"} +(20,1,1) = {" +dD +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +Aj +hK +hK +hK +hK +It +"} +(21,1,1) = {" +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +"} +(22,1,1) = {" +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +"} +(23,1,1) = {" +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +hK +"} +(24,1,1) = {" +hK +hK +hK +hK +hK +hK +hK +hK +dD +Mf +dD +hK +xd +Yi +dD +hK +dD +hK +dD +"} +(25,1,1) = {" +hK +dD +hK +dD +Gt +Gt +wf +Gt +Gt +Gt +Gt +wf +Gt +cl +Gt +cl +Gt +Gt +Gt +"} +(26,1,1) = {" +Gt +Gt +Gt +Gt +wf +It +It +bF +It +It +RP +Gt +It +bF +It +It +It +Gt +dD +"} +(27,1,1) = {" +NG +dD +It +Gt +cl +ng +tN +ng +It +Uw +RH +ng +It +ng +ng +tN +It +dD +NG +"} +(28,1,1) = {" +NG +dD +dD +Gt +It +TU +ng +LJ +It +tN +WI +oV +It +NE +sJ +QD +It +dD +NG +"} +(29,1,1) = {" +NG +dD +It +Gt +cl +WF +mA +hb +It +bK +Mf +AO +It +eo +ng +ng +It +dD +NG +"} +(30,1,1) = {" +NG +dD +SH +Gt +wD +HJ +BX +It +It +It +My +It +It +It +Ax +Ks +It +dD +NG +"} +(31,1,1) = {" +It +dD +SH +Aj +It +ng +sJ +It +IL +sf +Yg +Oq +Tb +It +It +nG +It +dD +NG +"} +(32,1,1) = {" +NG +dD +dD +Aj +It +jU +Bf +It +MC +Yg +Yg +Mb +eG +It +zG +AC +It +dD +NG +"} +(33,1,1) = {" +NG +dD +dD +Aj +Oe +It +It +It +Oz +kv +hb +sJ +vA +It +It +It +Oe +dD +NG +"} +(34,1,1) = {" +NG +dD +dD +Gt +Oe +tH +tH +It +oF +zM +zM +zM +oD +It +tH +tH +Oe +dD +NG +"} +(35,1,1) = {" +NG +dD +dD +Gt +Aj +ma +ma +Oe +Oe +It +It +It +Oe +Oe +ma +Aj +Yf +dD +NG +"} +(36,1,1) = {" +NG +NG +dD +dD +SH +Aj +Aj +Oe +tH +tH +tH +tH +tH +Oe +Aj +SH +SH +dD +NG +"} +(37,1,1) = {" +NG +NG +dD +dD +SH +SH +SH +SH +ma +ma +ma +ma +ma +SH +SH +SH +RK +dD +NG +"} +(38,1,1) = {" +NG +NG +dD +dD +dD +SH +SH +dD +dD +dD +dD +dD +dD +dD +SH +SH +SH +dD +NG +"} +(39,1,1) = {" +NG +NG +dD +dD +SH +dD +Yf +SH +dD +SH +SH +SH +dD +SH +dD +SH +SH +NG +NG +"} +(40,1,1) = {" +NG +NG +NG +dD +SH +SH +SH +SH +SH +SH +SH +SH +SH +SH +SH +dD +SH +NG +NG +"} diff --git a/_maps/map_files/RandomZLevels/beach.dmm b/_maps/map_files/RandomZLevels/beach.dmm deleted file mode 100644 index ccfb284c8ea..00000000000 --- a/_maps/map_files/RandomZLevels/beach.dmm +++ /dev/null @@ -1,5436 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aa" = ( -/turf/space, -/area/space) -"bc" = ( -/obj/structure/flora/ausbushes/leafybush, -/obj/effect/decal/snow/sand/edge{ - dir = 9; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bd" = ( -/obj/structure/flora/grass/brown, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"be" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 5; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bf" = ( -/obj/structure/flora/ausbushes/genericbush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bg" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 8; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bh" = ( -/obj/structure/flora/ausbushes/leafybush, -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bi" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bj" = ( -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bk" = ( -/obj/effect/decal/snow/sand/surround{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bl" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bm" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 9; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bn" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/turf/simulated/floor/grass, -/area/awaymission/beach) -"bo" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 10; - name = "rough sand" - }, -/turf/simulated/floor/grass, -/area/awaymission/beach) -"bp" = ( -/obj/effect/decal/snow/sand/surround{ - name = "rough sand" - }, -/turf/simulated/floor/grass, -/area/awaymission/beach) -"bq" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 6; - name = "rough sand" - }, -/turf/simulated/floor/grass, -/area/awaymission/beach) -"br" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 6; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bs" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 10; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bt" = ( -/obj/structure/flora/ausbushes/lavendergrass, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bu" = ( -/obj/structure/flora/ausbushes/leafybush, -/obj/effect/decal/snow/sand/edge{ - dir = 9; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bv" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 5; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bw" = ( -/obj/effect/overlay/palmtree_r, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bx" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 9; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"by" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bz" = ( -/obj/effect/overlay/palmtree_r, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bA" = ( -/obj/structure/flora/ausbushes/genericbush, -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bB" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bC" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bD" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/overlay/coconut, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bE" = ( -/obj/structure/flora/bush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bF" = ( -/obj/effect/overlay/palmtree_l, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bG" = ( -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bH" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 8; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bI" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bJ" = ( -/obj/effect/overlay/palmtree_l, -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bK" = ( -/obj/effect/overlay/palmtree_l, -/obj/effect/overlay/coconut, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bL" = ( -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bM" = ( -/obj/structure/flora/ausbushes/sunnybush, -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bN" = ( -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bO" = ( -/obj/structure/flora/grass/brown, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bP" = ( -/obj/structure/flora/rock/pile, -/obj/effect/overlay/palmtree_l, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bQ" = ( -/obj/structure/flora/ausbushes/grassybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bR" = ( -/obj/structure/flora/ausbushes/reedbush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bS" = ( -/obj/structure/flora/grass/green, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"bT" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/palebush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bU" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/genericbush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bV" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bW" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bX" = ( -/obj/structure/flora/rock, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bY" = ( -/obj/structure/flora/ausbushes/palebush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"bZ" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/lavendergrass, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"ca" = ( -/obj/structure/flora/rock/pile, -/obj/effect/overlay/palmtree_r, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cb" = ( -/obj/structure/flora/rock/pile, -/obj/effect/overlay/palmtree_l, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cc" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/fernybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cd" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ce" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cf" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/fernybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cg" = ( -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"ch" = ( -/obj/structure/flora/rock, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ci" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/overlay/coconut, -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cm" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/palebush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cq" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/obj/structure/closet/crate/internals, -/obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cr" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/obj/structure/dispenser/oxygen, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cs" = ( -/obj/structure/flora/ausbushes/reedbush, -/obj/effect/decal/snow/sand/edge{ - dir = 5; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ct" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/overlay/coconut, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cu" = ( -/obj/structure/flora/ausbushes/lavendergrass, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cv" = ( -/obj/structure/flora/bush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cx" = ( -/obj/structure/flora/ausbushes/genericbush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cB" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/obj/effect/overlay/palmtree_r, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cC" = ( -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"cE" = ( -/turf/simulated/wall/mineral/sandstone, -/area/awaymission/beach) -"cG" = ( -/obj/structure/flora/ausbushes/ppflowers, -/obj/effect/decal/snow/sand/edge{ - dir = 8; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cJ" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/obj/structure/closet/athletic_mixed, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cK" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 8; - name = "rough sand" - }, -/obj/effect/overlay/palmtree_l, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cL" = ( -/obj/structure/mineral_door/wood, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cN" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 4; - name = "rough sand" - }, -/obj/item/clothing/shoes/sandal, -/obj/item/clothing/shoes/sandal, -/obj/item/clothing/shoes/sandal, -/obj/structure/closet/crate, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cO" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cQ" = ( -/turf/simulated/wall/mineral/titanium, -/area/awaymission/beach) -"cS" = ( -/obj/structure/closet/gmcloset{ - name = "formal wardrobe" - }, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cT" = ( -/obj/structure/closet/crate, -/obj/item/gun/energy/laser/retro, -/obj/item/gun/energy/laser/retro, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cU" = ( -/obj/structure/closet/secure_closet/bar, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cV" = ( -/obj/structure/table/wood, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cW" = ( -/obj/structure/table/wood, -/obj/item/book/manual/barman_recipes, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cX" = ( -/obj/structure/table/wood, -/obj/item/reagent_containers/drinks/shaker, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"cY" = ( -/obj/structure/flora/rock/pile, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"cZ" = ( -/obj/machinery/economy/vending/boozeomat{ - emagged = 1 - }, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"da" = ( -/obj/structure/table/wood, -/obj/item/clothing/glasses/sunglasses, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"db" = ( -/obj/machinery/economy/vending/cola, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dc" = ( -/obj/structure/flora/ausbushes/palebush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dd" = ( -/mob/living/simple_animal/crab, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"de" = ( -/obj/effect/overlay/coconut, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"df" = ( -/mob/living/simple_animal/crab/Coffee, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dg" = ( -/obj/structure/chair, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dh" = ( -/obj/structure/flora/ausbushes/reedbush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"di" = ( -/obj/structure/flora/rock/pile, -/obj/structure/flora/ausbushes/stalkybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"dj" = ( -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"dk" = ( -/turf/simulated/floor/beach/away/coastline/dense, -/area/awaymission/beach) -"dl" = ( -/obj/machinery/economy/vending/cigarette, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dm" = ( -/obj/machinery/economy/vending/snack, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dn" = ( -/obj/structure/curtain/open, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"do" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dq" = ( -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dr" = ( -/turf/simulated/floor/beach/away/water, -/area/awaymission/beach) -"ds" = ( -/turf/simulated/floor/beach/away/water/dense, -/area/awaymission/beach) -"dt" = ( -/turf/simulated/floor/beach/away/water/drop, -/area/awaymission/beach) -"du" = ( -/turf/simulated/floor/beach/away/water/deep, -/area/awaymission/beach) -"dw" = ( -/turf/simulated/floor/beach/away/water/deep/dense, -/area/awaymission/beach) -"dx" = ( -/turf/simulated/floor/beach/away/water/drop/dense, -/area/awaymission/beach) -"dy" = ( -/turf/simulated/floor/beach/away/water/edge_drop, -/area/awaymission/beach) -"dz" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 10; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dA" = ( -/obj/structure/mineral_door/wood, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dB" = ( -/obj/structure/flora/grass/green, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"dC" = ( -/obj/structure/table/wood, -/obj/machinery/chem_dispenser/soda, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dE" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dF" = ( -/obj/structure/table/wood, -/obj/machinery/chem_dispenser/beer, -/turf/simulated/floor/wood, -/area/awaymission/beach) -"dG" = ( -/obj/structure/flora/grass/green, -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"dH" = ( -/obj/effect/decal/snow/sand/edge{ - dir = 1; - name = "rough sand" - }, -/obj/structure/chair/stool/bar, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dI" = ( -/obj/structure/table/wood, -/obj/item/clothing/glasses/eyepatch, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dJ" = ( -/obj/structure/table/wood, -/obj/item/clothing/head/bandana, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dK" = ( -/obj/item/ship_in_a_bottle, -/obj/structure/table/wood, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dL" = ( -/mob/living/simple_animal/hostile/pirate/ranged{ - loot = list(/obj/effect/mob_spawn/human/corpse/pirate/ranged) - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dM" = ( -/obj/structure/table/wood, -/obj/item/clothing/head/collectable/pirate, -/obj/item/stack/sheet/mineral/diamond{ - amount = 2 - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dN" = ( -/obj/structure/closet/crate, -/obj/item/stack/sheet/mineral/uranium{ - amount = 20 - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dO" = ( -/obj/structure/chair/office/light, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dP" = ( -/obj/effect/overlay/palmtree_r, -/obj/effect/decal/snow/sand/edge{ - dir = 6; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dQ" = ( -/obj/structure/chair/office/light, -/mob/living/simple_animal/hostile/pirate/ranged{ - loot = list(/obj/effect/mob_spawn/human/corpse/pirate/ranged) - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dR" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/chair/comfy/shuttle{ - dir = 4 - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"dS" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/chair/comfy/shuttle{ - dir = 8 - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"dT" = ( -/obj/effect/overlay/palmtree_l, -/obj/effect/decal/snow/sand/edge{ - dir = 8; - name = "rough sand" - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dU" = ( -/obj/effect/spawner/window/shuttle, -/turf/simulated/floor/plating, -/area/awaymission/beach) -"dV" = ( -/obj/structure/flora/rock, -/obj/structure/flora/ausbushes/leafybush, -/turf/simulated/floor/beach/away/sand/dense, -/area/awaymission/beach) -"dX" = ( -/obj/item/paper, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"dZ" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 4 - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"eb" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 8 - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"ec" = ( -/obj/machinery/computer/nonfunctional, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"ed" = ( -/obj/structure/closet/crate, -/obj/item/clothing/under/costume/pirate, -/obj/item/clothing/under/costume/pirate, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ee" = ( -/obj/structure/closet/crate, -/obj/item/clothing/suit/pirate_brown, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ef" = ( -/obj/effect/overlay/palmtree_r, -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"eg" = ( -/mob/living/simple_animal/hostile/pirate{ - loot = list(/obj/effect/mob_spawn/human/corpse/pirate) - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"eh" = ( -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"ei" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 1 - }, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"ej" = ( -/obj/structure/table/wood, -/obj/item/clothing/suit/pirate_black, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ek" = ( -/obj/effect/decal/snow/sand/edge{ - name = "rough sand" - }, -/obj/structure/flora/ausbushes/sunnybush, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"el" = ( -/obj/machinery/door/airlock/titanium, -/turf/simulated/floor/mineral/titanium/blue, -/area/awaymission/beach) -"em" = ( -/obj/item/beach_ball, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"en" = ( -/mob/living/simple_animal/hostile/pirate{ - loot = list(/obj/effect/mob_spawn/human/corpse/pirate) - }, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"eo" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 75 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"ep" = ( -/obj/effect/decal/cleanable/blood, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"eq" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 192 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"er" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 104 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"es" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"et" = ( -/obj/structure/shuttle/engine/heater, -/turf/simulated/floor/plating, -/area/awaymission/beach) -"eu" = ( -/obj/structure/table/wood, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ev" = ( -/obj/structure/table/wood, -/obj/item/food/snacks/pie, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"ew" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 44 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"ex" = ( -/obj/structure/shuttle/engine/propulsion{ - icon_state = "propulsion_l" - }, -/turf/simulated/floor/plating, -/area/awaymission/beach) -"ey" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 97 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"ez" = ( -/obj/structure/shuttle/engine/propulsion{ - icon_state = "propulsion_r" - }, -/turf/simulated/floor/plating, -/area/awaymission/beach) -"eA" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/simulated/floor/plating, -/area/awaymission/beach) -"eB" = ( -/obj/effect/waterfall{ - dir = 1; - water_frequency = 94 - }, -/turf/simulated/floor/beach/away/coastline, -/area/awaymission/beach) -"eC" = ( -/obj/structure/table/wood, -/obj/effect/decal/cleanable/blood, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"eD" = ( -/obj/structure/closet/crate/can, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"eE" = ( -/obj/structure/closet/crate, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"kX" = ( -/turf/simulated/wall/indestructible/sandstone, -/area/awaymission/beach) -"nL" = ( -/turf/simulated/wall/indestructible/sandstone, -/area/space) -"sF" = ( -/obj/effect/baseturf_helper/beach/away/sand, -/turf/simulated/floor/beach/away/sand, -/area/awaymission/beach) -"LZ" = ( -/obj/machinery/poolcontroller/invisible, -/turf/simulated/floor/beach/away/water/deep, -/area/awaymission/beach) - -(1,1,1) = {" -nL -cg -cg -bw -cu -dh -cg -bw -cg -bw -by -bS -bj -bF -dz -dB -dh -cg -bB -bj -bF -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dy -du -du -du -du -du -"} -(2,1,1) = {" -nL -cg -bw -bx -bH -bg -bH -bg -bH -cG -bj -bz -bR -bj -bz -bg -bg -dT -bD -bj -bE -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(3,1,1) = {" -nL -bX -cg -bJ -bj -bD -bj -bz -bz -bj -bj -bD -bj -bN -bQ -bO -bz -bz -bj -bD -bF -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(4,1,1) = {" -nL -bd -bm -bj -bD -bj -bK -bD -bj -bz -bQ -bj -bz -bN -bF -bj -bK -bj -bz -bj -bz -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(5,1,1) = {" -nL -bc -bt -bj -bz -bD -bj -bS -bj -bz -bj -bF -bj -bz -bz -bj -bz -bj -bz -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(6,1,1) = {" -nL -be -bl -bD -bE -bj -bz -bf -bj -bL -cm -ch -bj -bL -bj -bf -bf -bj -dc -bL -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(7,1,1) = {" -nL -cg -bw -by -bz -bN -bf -bT -bX -bW -bV -bX -bW -bV -bW -cc -bX -bW -bX -bV -bW -dh -dk -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -dt -du -du -du -du -du -"} -(8,1,1) = {" -nL -cg -bw -bB -bj -bt -bj -bU -cd -bj -bj -bj -bj -bj -bj -cd -cY -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(9,1,1) = {" -nL -cg -bw -bB -bF -bz -bN -bV -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -eo -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(10,1,1) = {" -nL -cg -bx -bj -bz -bz -bj -bW -bj -bj -bj -bj -bj -bj -bj -bz -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(11,1,1) = {" -nL -bg -bj -bE -bj -bD -bL -bX -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -dd -bj -em -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(12,1,1) = {" -nL -bf -bj -bz -bz -bj -bz -bU -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(13,1,1) = {" -nL -bh -bj -bz -bz -bj -bj -bV -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -eq -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(14,1,1) = {" -nL -cg -bA -bD -bt -bE -bf -bW -bj -bj -bj -bj -sF -bj -bj -bj -bj -bj -bj -bF -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(15,1,1) = {" -nL -bX -by -bF -bj -bz -bj -bT -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -de -bj -bj -er -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(16,1,1) = {" -nL -cg -bB -bj -bF -bF -bf -bU -bj -bj -bK -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(17,1,1) = {" -nL -cg -bB -bj -bz -bz -bz -bX -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(18,1,1) = {" -nL -cg -by -bE -bj -bj -bj -bY -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -dd -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(19,1,1) = {" -nL -bk -bj -bz -bj -bt -bj -bV -bj -bj -bj -bl -bl -bl -bl -bl -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(20,1,1) = {" -nL -cg -by -bz -bD -bj -bN -bW -bj -bj -bi -cE -cE -cE -dA -cE -by -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(21,1,1) = {" -nL -bg -bC -bj -bF -bF -bj -bT -bj -bj -bi -cE -cS -dq -dq -dC -dH -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(22,1,1) = {" -nL -bi -bw -by -bj -bF -bj -bV -bj -bj -cq -cE -cU -dq -dq -dF -dH -bj -bj -bj -bj -bj -ew -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(23,1,1) = {" -nL -bj -bg -bz -bF -bK -bL -bX -bj -bj -cr -cE -cW -dq -dq -cV -dH -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(24,1,1) = {" -nL -bj -bj -bj -bz -bD -bj -bW -bj -bj -cq -cE -cX -dq -dq -cV -dH -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(25,1,1) = {" -nL -bl -bz -bE -bj -bj -bj -bV -bj -bj -bi -cE -cV -dq -dq -cV -dH -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(26,1,1) = {" -nL -cg -bB -bj -bz -bj -bP -bX -bj -bj -bi -cE -da -dq -dq -cV -dH -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(27,1,1) = {" -nL -cg -by -bj -bj -bz -bj -bT -bj -bj -bi -cE -cZ -dq -dq -cV -dH -bj -bj -bj -dg -bj -ey -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(28,1,1) = {" -nL -bm -bz -bz -bK -bj -bL -bZ -ce -bj -bi -cE -dl -dq -dq -cV -dH -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -dt -du -du -du -du -"} -(29,1,1) = {" -nL -bj -bj -bz -bj -bK -bj -ca -bj -bj -bi -cE -db -dq -dq -cV -dH -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -dx -dt -du -du -dt -dt -du -"} -(30,1,1) = {" -nL -bl -bl -bF -bj -bz -bj -bX -cf -bj -bi -cE -dm -dq -dq -cV -dH -bj -bj -bF -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -dt -dw -du -du -du -du -dt -du -"} -(31,1,1) = {" -nL -cg -bw -by -bE -bj -bQ -bT -cd -bj -bi -cE -cE -cE -cE -cE -by -bj -bj -bj -dg -bj -er -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -dw -du -du -du -du -dt -du -"} -(32,1,1) = {" -nL -cg -cg -bJ -bj -bD -bj -cb -bj -bj -bj -bg -bg -bg -bg -bg -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -dw -du -du -du -du -dt -du -"} -(33,1,1) = {" -nL -cg -cg -by -bj -bF -bf -bV -bj -bj -cJ -cN -bl -bj -bj -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -dt -dw -du -du -dt -du -du -du -"} -(34,1,1) = {" -nL -cg -bw -by -bD -bL -bj -cc -bj -bi -cE -cE -cE -by -bj -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -dx -du -du -du -du -du -du -"} -(35,1,1) = {" -nL -cg -bX -by -bz -bj -bN -bX -bj -bi -cE -cO -dn -by -bj -bF -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dx -dt -du -du -du -du -du -"} -(36,1,1) = {" -nL -bo -bd -bB -bE -bz -bj -bW -bj -bi -cE -cE -cE -by -bj -bj -bj -bj -bj -df -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(37,1,1) = {" -nL -bn -cg -bM -bj -bj -bN -ca -bj -bj -bg -bg -bg -bj -bj -bj -bj -bj -bj -bj -bj -bj -ey -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(38,1,1) = {" -nL -bn -cg -ci -bf -bL -bj -cc -bj -bj -cJ -cN -bl -bj -bj -em -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(39,1,1) = {" -nL -bq -bw -by -bj -bz -bf -bX -bj -bi -cE -cE -cE -by -bj -bj -bj -bj -bz -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(40,1,1) = {" -nL -cg -bG -by -bz -bj -bj -bT -bj -bi -cE -cO -dn -by -bj -bj -bj -bj -bj -de -bj -bj -eB -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(41,1,1) = {" -nL -bp -cg -by -bL -bj -bN -bV -bj -bi -cE -cE -cE -by -bF -bj -bj -bj -bj -bj -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(42,1,1) = {" -nL -cg -cg -bB -bj -bz -bj -bW -bj -bj -bg -bg -bg -bj -bj -bj -bj -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(43,1,1) = {" -nL -cg -cg -bB -bj -bD -bj -cc -bj -bj -cJ -cN -bl -bj -bj -bj -bj -bj -bj -bj -bj -bj -ey -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(44,1,1) = {" -nL -bg -bH -bj -bz -bz -bL -bX -bj -bi -cE -cE -cE -by -bj -bj -bj -bj -bj -bj -dg -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(45,1,1) = {" -nL -bj -bj -bj -bz -bj -bR -cb -bf -bi -cE -cO -dn -by -bj -bj -bj -bj -bj -bj -bj -bj -eq -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(46,1,1) = {" -nL -bj -bl -bC -bj -bz -bf -bX -bz -bi -cE -cE -cE -by -bj -bj -bj -bj -bj -bz -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(47,1,1) = {" -nL -br -bw -cg -by -bj -bN -bT -cf -bj -cK -bg -bg -bj -bj -bj -bj -bj -bj -bj -bj -bz -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -ds -dt -du -du -du -du -du -"} -(48,1,1) = {" -nL -cg -bX -cg -bB -bL -bj -ca -cg -bW -bV -bW -bX -cc -bV -bW -bX -cc -bV -bX -bW -di -dk -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -ds -dt -du -du -du -du -du -"} -(49,1,1) = {" -nL -cg -cg -cg -ci -bE -bj -bj -ch -bD -bf -ch -bL -bj -bz -bf -bz -bL -bz -bj -bN -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(50,1,1) = {" -nL -cg -cg -bx -bz -bj -bL -bL -bj -bj -bz -bz -bQ -bj -bz -bj -bR -bj -bK -bE -bj -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(51,1,1) = {" -nL -bs -cg -by -bj -bz -bj -bz -bK -bj -bz -bO -bK -bL -bj -bz -bj -bO -bz -bS -bz -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(52,1,1) = {" -nL -br -bw -cs -bj -bj -bj -bR -cB -bl -bl -bl -bz -bz -bz -bj -bD -bj -bD -bj -bz -bj -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(53,1,1) = {" -nL -cg -cg -cg -bB -bO -bj -bi -bw -bw -cv -cg -bJ -bR -bj -bl -dP -bG -be -bz -bS -bz -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dt -du -du -du -du -du -"} -(54,1,1) = {" -nL -cg -cg -cg -by -bj -bz -dE -cC -bX -bG -cC -do -ef -ek -dG -cC -bw -dV -bD -bj -bz -dj -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dr -dy -du -du -du -du -LZ -"} -(55,1,1) = {" -nL -cg -bw -by -bE -bj -bQ -bT -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -be -bC -bF -bJ -bj -bD -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -"} -(56,1,1) = {" -nL -cg -cg -bJ -bj -bD -bj -cb -bj -bj -bj -cQ -cQ -cQ -el -el -cQ -cQ -cQ -bj -bj -cb -by -bj -bF -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(57,1,1) = {" -nL -cg -cg -by -bj -bF -bf -bV -bj -bj -bj -cQ -dZ -eg -eh -eh -dR -et -ex -bj -bf -bV -by -bD -bL -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(58,1,1) = {" -nL -cg -bw -by -bD -bL -bj -cc -bj -bj -bj -dU -ec -ei -eh -eh -eh -et -eA -bj -bj -cc -by -bz -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(59,1,1) = {" -nL -cg -bX -by -bz -bj -bN -bX -bj -bj -bj -cQ -eb -eh -eh -eh -dS -et -ez -bj -bN -bX -bB -bE -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(60,1,1) = {" -nL -bo -bd -bB -bE -bz -bj -bW -bj -bj -bj -cQ -cQ -cQ -el -el -cQ -cQ -cQ -bj -bj -bW -bM -bj -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(61,1,1) = {" -nL -bn -cg -bM -bj -bj -bN -ca -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bN -ca -ci -bf -bL -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(62,1,1) = {" -nL -bn -cg -ci -bf -bL -bj -cc -cE -cE -cE -cE -cE -cE -bj -bj -bj -bj -bj -bj -bj -cc -by -bj -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(63,1,1) = {" -nL -bq -bw -by -bj -bz -bf -bX -cE -dr -dr -dr -dr -dr -bj -bj -bj -bj -bj -bj -bf -bX -by -bz -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(64,1,1) = {" -nL -cg -bG -by -bz -bj -bj -bT -cE -dr -dr -dr -dr -dr -bj -ep -bj -es -es -bj -bj -bT -by -bL -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(65,1,1) = {" -nL -bp -cg -by -bL -bj -bN -bV -cE -dr -dr -dr -dr -dr -dL -bj -es -eu -eu -bj -bN -bV -bB -bj -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(66,1,1) = {" -nL -cg -cg -bB -bj -bz -bj -bW -cE -dr -dr -dr -dr -dr -dX -bj -es -ev -eC -bj -bj -bW -bB -bj -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(67,1,1) = {" -nL -cg -cg -bB -bj -bD -bj -cc -cE -dr -dr -dr -dr -dr -bj -bj -bj -es -es -bj -bj -cc -bj -bz -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(68,1,1) = {" -nL -bg -bH -bj -bz -bz -bL -bX -cE -cE -cE -cE -cE -cE -bj -bj -bj -ep -bj -bj -bL -bX -bj -bz -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(69,1,1) = {" -nL -bj -bj -bj -bz -bj -bR -cb -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bj -bR -cb -bC -bj -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(70,1,1) = {" -nL -bj -bl -bC -bj -bz -bf -bX -kX -kX -kX -kX -kX -kX -kX -kX -kX -cL -cL -kX -bf -bX -cg -by -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(71,1,1) = {" -nL -br -bw -cg -by -bj -bN -bT -kX -dI -dO -kX -bj -dL -bj -cL -bj -bj -bj -kX -bN -bT -cg -bB -bL -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(72,1,1) = {" -nL -cg -bX -cg -bB -bL -bj -ca -kX -dK -bj -kX -bj -bj -bj -kX -bj -bj -bj -kX -bj -ca -cg -ci -bE -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(73,1,1) = {" -nL -cg -cg -cg -ci -bE -bj -bj -kX -dJ -bj -kX -ed -bj -bj -kX -bj -en -bj -kX -bj -bj -bx -bz -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(74,1,1) = {" -nL -cg -cg -bx -bz -bj -bL -bL -kX -bj -bj -kX -ee -bj -bj -cL -bj -bj -bj -kX -bL -bL -by -bj -bz -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(75,1,1) = {" -nL -bs -cg -by -bj -bz -bj -bz -kX -kX -cL -kX -kX -kX -kX -kX -kX -bj -bj -kX -bj -bz -bJ -bj -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(76,1,1) = {" -nL -bX -cg -bJ -bj -bD -bj -bz -kX -dL -bj -bj -cL -bj -bj -bj -bj -bj -bj -kX -bj -bz -bj -bD -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(77,1,1) = {" -nL -bd -bm -bj -bD -bj -bK -bj -kX -bj -bj -bj -cL -bj -en -bj -bj -bj -bj -kX -bK -bj -bJ -bj -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(78,1,1) = {" -nL -bX -cg -bJ -bj -bD -bj -bz -kX -dL -bj -bj -cL -bj -bj -bj -bj -bj -bj -kX -bj -bz -bj -bD -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(79,1,1) = {" -nL -bd -bm -bj -bD -bj -bK -bD -kX -kX -kX -cL -kX -kX -kX -kX -kX -bj -bj -kX -bK -bD -bj -bz -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(80,1,1) = {" -nL -bc -bt -bj -bz -bD -bj -bS -kX -dN -bj -bj -kX -ej -bj -bj -cL -bj -bj -eE -bf -bX -bj -bD -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(81,1,1) = {" -nL -be -bl -bD -bE -bj -bz -bf -kX -dM -dQ -cT -kX -bj -dL -bj -cL -bj -bj -eD -bN -bT -bD -bj -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(82,1,1) = {" -nL -cg -bw -by -bz -bN -bf -bT -kX -kX -kX -kX -kX -kX -kX -kX -kX -kX -kX -kX -bj -ca -bj -bD -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(83,1,1) = {" -nL -cg -cg -bw -cu -dh -cg -bw -cg -bw -by -bS -bj -bF -dz -dB -dh -cg -bB -bj -bF -bj -bD -bj -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(84,1,1) = {" -nL -cg -bw -bx -bH -bg -bH -bg -bH -cG -bj -bz -bR -bj -bz -bg -bg -dT -bD -bj -bE -bj -bz -bD -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(85,1,1) = {" -nL -bX -cg -bJ -bj -bD -bj -bz -bz -bj -bj -bD -bj -bN -bQ -bO -bz -bz -bj -bD -bF -bj -by -bz -bD -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(86,1,1) = {" -nL -bd -bm -bj -bD -bj -bK -bD -bj -bz -bQ -bj -bz -bN -bF -bj -bK -bj -bz -bj -bz -bj -bB -by -bj -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(87,1,1) = {" -nL -bu -bt -bj -bz -bD -bj -bS -bj -bz -bj -bF -bj -bz -bz -bj -bz -bj -bz -bj -bj -bj -ci -bB -bL -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(88,1,1) = {" -nL -bv -bI -ct -cv -bj -bw -cx -bj -bG -bT -ch -cg -bG -cg -cx -bf -cg -dc -bL -cg -cg -cg -ci -bE -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(89,1,1) = {" -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -nL -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} diff --git a/_maps/map_files/generic/centcomm.dmm b/_maps/map_files/generic/centcomm.dmm index 95e4b026505..6949d75e90f 100644 --- a/_maps/map_files/generic/centcomm.dmm +++ b/_maps/map_files/generic/centcomm.dmm @@ -490,6 +490,11 @@ icon_state = "green" }, /area/holodeck/source_emptycourt) +"cb" = ( +/obj/structure/closet/abductor, +/obj/item/storage/belt/janitor/abductor/full, +/turf/simulated/floor/plating/abductor, +/area/abductor_ship) "cc" = ( /obj/structure/window/reinforced{ dir = 1 @@ -40679,63 +40684,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -40936,63 +40941,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -41193,63 +41198,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -41450,63 +41455,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -41707,63 +41712,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -41964,63 +41969,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -42221,63 +42226,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -42478,63 +42483,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -42735,63 +42740,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -42992,63 +42997,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -43249,63 +43254,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -43506,63 +43511,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -43763,63 +43768,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -44020,63 +44025,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -44277,63 +44282,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -44534,63 +44539,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -44791,63 +44796,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -45048,63 +45053,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -45305,63 +45310,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -45562,63 +45567,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -45819,63 +45824,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -46076,63 +46081,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -46333,63 +46338,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -46590,63 +46595,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -46742,7 +46747,7 @@ aN aN lz lz -nr +cb bK nr lz @@ -46756,7 +46761,7 @@ aN aN lz lz -nr +cb bK nr lz @@ -46847,63 +46852,63 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck +ck aN aN aN @@ -50340,7 +50345,7 @@ aN aN lz lz -nr +cb bK nr lz @@ -50354,7 +50359,7 @@ aN aN lz lz -nr +cb bK nr lz diff --git a/_maps/map_files/shuttles/emergency_lance.dmm b/_maps/map_files/shuttles/emergency_lance.dmm new file mode 100644 index 00000000000..ad94624ae31 --- /dev/null +++ b/_maps/map_files/shuttles/emergency_lance.dmm @@ -0,0 +1,2168 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ae" = ( +/obj/machinery/door/airlock/command/glass{ + name = "Cockpit" + }, +/obj/effect/mapping_helpers/airlock/access/all/command/general, +/obj/machinery/door/poddoor/preopen{ + id = "ravenbridgeblast"; + name = "Cockpit Blast Door"; + id_tag = "ravenbridgeblast" + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"av" = ( +/turf/simulated/wall/mineral/plastitanium/nodiagonal, +/area/shuttle/escape) +"bm" = ( +/obj/structure/shuttle/engine/propulsion/burst/left, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"bo" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"bA" = ( +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"bO" = ( +/obj/structure/shuttle/engine/propulsion/burst/right{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"bQ" = ( +/obj/machinery/sleeper, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"bV" = ( +/obj/structure/table/reinforced, +/obj/machinery/recharger, +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"cn" = ( +/obj/structure/table/reinforced, +/obj/item/rcd/preloaded, +/obj/item/rcd_ammo, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/shuttle/escape) +"cF" = ( +/obj/structure/closet/crate/freezer/iv_storage, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"dq" = ( +/obj/machinery/door/airlock/highsecurity, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"dP" = ( +/obj/structure/shuttle/engine/propulsion/burst/right, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"eh" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"ek" = ( +/obj/machinery/door/airlock/engineering{ + name = "Emergency Shutle Engineering" + }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"ew" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"eL" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"eP" = ( +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"fE" = ( +/turf/simulated/wall/mineral/plastitanium, +/area/shuttle/escape) +"fG" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/standard_unit, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"fH" = ( +/obj/structure/table/reinforced, +/obj/item/storage/firstaid/doctor, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"fL" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"fR" = ( +/obj/machinery/turretid/lethal{ + req_access = list(18); + check_access = 0; + check_arrest = 0; + check_records = 0; + pixel_y = -32 + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"gs" = ( +/obj/structure/sign/lifestar, +/turf/simulated/wall/mineral/plastitanium/nodiagonal, +/area/shuttle/escape) +"gN" = ( +/obj/machinery/economy/vending/wallmed{ + name = "Emergency NanoMed"; + pixel_y = 28 + }, +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"gS" = ( +/obj/structure/fans/tiny/invisible, +/obj/machinery/door/airlock/external/glass, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"gU" = ( +/obj/structure/extinguisher_cabinet{ + name = "north bump"; + pixel_y = 30 + }, +/obj/structure/bed/roller, +/obj/machinery/iv_drip, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"gX" = ( +/obj/structure/closet/crate/freezer/iv_storage, +/obj/item/reagent_containers/hypospray/autoinjector/survival, +/obj/item/reagent_containers/hypospray/autoinjector/survival, +/obj/item/reagent_containers/hypospray/autoinjector/survival, +/obj/item/reagent_containers/hypospray/autoinjector/survival, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"gZ" = ( +/obj/effect/spawner/window/plastitanium, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"hs" = ( +/obj/structure/extinguisher_cabinet{ + name = "south bump"; + pixel_y = -30 + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow"; + dir = 1 + }, +/area/shuttle/escape) +"hv" = ( +/obj/machinery/door/airlock/external{ + id_tag = "s_docking_airlock" + }, +/obj/structure/fans/tiny/invisible, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"ii" = ( +/obj/machinery/door/airlock/medical{ + id_tag = "mental_health"; + name = "Mental Health Crisis Room" + }, +/turf/simulated/floor/mineral/silver, +/area/shuttle/escape) +"it" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"iJ" = ( +/turf/template_noop, +/area/template_noop) +"iY" = ( +/obj/structure/chair/office/dark{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"jn" = ( +/obj/structure/bed, +/obj/item/bedsheet/medical, +/obj/item/toy/plushie/lizardplushie{ + name = "Calms-Thy-Panic" + }, +/turf/simulated/floor/mineral/silver, +/area/shuttle/escape) +"jp" = ( +/obj/structure/chair/office/dark, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/shuttle/escape) +"jr" = ( +/obj/machinery/economy/vending/wallmed{ + name = "Emergency NanoMed"; + pixel_x = -28 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"jK" = ( +/obj/machinery/porta_turret/ai_turret, +/turf/simulated/wall/mineral/plastitanium, +/area/shuttle/escape) +"jZ" = ( +/obj/machinery/computer/aifixer{ + dir = 4 + }, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"kg" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"kr" = ( +/obj/structure/chair/office/dark, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"ku" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"kO" = ( +/obj/structure/window/reinforced, +/obj/structure/shuttle/engine/heater{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"kZ" = ( +/obj/machinery/computer/crew, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"lj" = ( +/obj/structure/shuttle/engine/propulsion/burst{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"lH" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"mS" = ( +/obj/structure/bed/roller, +/obj/machinery/iv_drip, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"mV" = ( +/mob/living/simple_animal/bot/medbot, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"nP" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"nX" = ( +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"ob" = ( +/obj/structure/chair/office/dark, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"of" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"ok" = ( +/obj/structure/reagent_dispensers/fueltank, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellowcorners" + }, +/area/shuttle/escape) +"pV" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow"; + dir = 1 + }, +/area/shuttle/escape) +"qb" = ( +/obj/structure/shuttle/engine/heater, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"qk" = ( +/obj/structure/marker_beacon/dock_marker, +/turf/simulated/floor/catwalk, +/area/shuttle/escape) +"qS" = ( +/obj/machinery/optable, +/obj/structure/extinguisher_cabinet{ + name = "west bump"; + pixel_x = -27 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"rd" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"rg" = ( +/obj/structure/rack, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"rp" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"rX" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"sx" = ( +/obj/machinery/shieldgen/raven, +/obj/effect/turf_decal/delivery/white/hollow, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"sE" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/suit_storage_unit/standard_unit, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"sT" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"tW" = ( +/obj/structure/chair/comfy/shuttle, +/obj/item/radio/intercom{ + name = "west bump"; + pixel_x = -28 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"uc" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"ul" = ( +/turf/simulated/floor/catwalk, +/area/shuttle/escape) +"ut" = ( +/obj/structure/table/reinforced, +/obj/item/storage/firstaid/doctor, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"uW" = ( +/obj/structure/window/reinforced, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/windoor/access/all/command{ + dir = 4 + }, +/obj/machinery/door/window/reinforced/normal{ + name = "Last Resort"; + dir = 4 + }, +/obj/structure/rack, +/obj/item/gun/energy/gun/mini{ + pixel_y = 6 + }, +/obj/item/gun/energy/gun/mini{ + pixel_y = -6 + }, +/obj/item/gun/energy/gun/mini, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"vk" = ( +/obj/structure/table/reinforced, +/obj/item/flash, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"vF" = ( +/obj/structure/shuttle/engine/propulsion/burst/left{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"wu" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/reagent_dispensers/watertank/high, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"ww" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/table/reinforced, +/obj/item/storage/surgical_tray, +/obj/item/stack/nanopaste, +/obj/item/reagent_containers/glass/bottle/reagent/hydrocodone, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"wx" = ( +/obj/machinery/computer/emergency_shuttle{ + dir = 8 + }, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"wz" = ( +/obj/machinery/door/airlock/security/glass{ + name = "Holding Area" + }, +/obj/effect/mapping_helpers/airlock/access/all/security/general, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"wF" = ( +/obj/machinery/atmospherics/portable/canister/oxygen, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"wS" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet{ + name = "west bump"; + pixel_x = -27 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"xj" = ( +/obj/machinery/economy/vending/wallmed{ + name = "Emergency NanoMed"; + pixel_x = -28 + }, +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"xv" = ( +/obj/structure/table/reinforced, +/obj/machinery/recharger, +/obj/machinery/door_control{ + id = "ravenbridgeblast"; + name = "Cockpick Airlock Blastdoor Control"; + pixel_x = 5; + req_access = list(19); + pixel_y = 10 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"xI" = ( +/obj/machinery/optable, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"yg" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"yA" = ( +/obj/item/defibrillator/loaded, +/obj/structure/table/reinforced, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"yD" = ( +/obj/docking_port/mobile/emergency{ + height = 50; + width = 19; + timid = 1; + dir = 2; + lance_docking = 1; + shuttle_speed_factor = 1.5 + }, +/obj/machinery/door/airlock/external{ + id_tag = "s_docking_airlock" + }, +/obj/structure/fans/tiny/invisible, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"yM" = ( +/obj/machinery/computer/crew{ + dir = 4 + }, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"zb" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"AK" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/light{ + dir = 8 + }, +/obj/effect/turf_decal/delivery/blue/partial{ + dir = 4 + }, +/obj/effect/turf_decal/delivery/blue/partial{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"AS" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/structure/table/reinforced, +/obj/item/stack/sheet/mineral/plasma/fifty, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/item/assembly/signaler, +/obj/item/assembly/signaler, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"Bi" = ( +/obj/structure/rack, +/obj/item/flashlight/flare, +/obj/item/flashlight/flare, +/obj/item/flashlight/flare, +/obj/item/flashlight/flare, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"Bn" = ( +/obj/machinery/suit_storage_unit/standard_unit, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Bx" = ( +/obj/structure/table/reinforced, +/obj/item/radio, +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"Cl" = ( +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/obj/machinery/hologram/holopad, +/obj/effect/turf_decal/box/white, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"CL" = ( +/obj/item/radio/intercom{ + name = "north bump"; + pixel_y = 28 + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"DD" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/shieldgen/raven, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"DU" = ( +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"DZ" = ( +/obj/structure/closet/fireaxecabinet{ + pixel_y = -32 + }, +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Ek" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/obj/item/radio/intercom{ + name = "east bump"; + pixel_x = 28 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"EV" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"FP" = ( +/obj/effect/mapping_helpers/airlock/access/all/medical/general, +/obj/machinery/door/airlock/medical/glass{ + id_tag = "MedbayFoyer"; + name = "Medical Supplies" + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Hk" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/storage/box/handcuffs, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"HE" = ( +/obj/machinery/light/small, +/obj/structure/table/reinforced, +/obj/item/book/manual/wiki/security_space_law{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/storage/firstaid/doctor, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"HK" = ( +/obj/structure/extinguisher_cabinet{ + name = "north bump"; + pixel_y = 30 + }, +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"HL" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/donkpockets, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Id" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/window/reinforced{ + dir = 4 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"If" = ( +/obj/structure/table/reinforced, +/obj/item/storage/firstaid/regular, +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"Iu" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"IF" = ( +/obj/machinery/suit_storage_unit/standard_unit, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"IJ" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"IN" = ( +/obj/structure/shuttle/engine/heater, +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"Jb" = ( +/obj/machinery/light/small, +/obj/machinery/computer/operating{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Jd" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Je" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/shuttle/engine/heater, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) +"Kg" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"Ko" = ( +/obj/machinery/computer/security{ + dir = 8; + network = list("SS13","Research Outpost","Mining Outpost") + }, +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Ky" = ( +/obj/machinery/light/small, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"KB" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/shieldgen/raven, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"KL" = ( +/obj/machinery/economy/vending/medical, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"KQ" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"KT" = ( +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/shuttle/escape) +"KY" = ( +/obj/machinery/light, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"Mb" = ( +/obj/machinery/shieldgen/raven, +/obj/effect/turf_decal/delivery/white/hollow, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Nc" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/chair/comfy/shuttle, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Nd" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"Nt" = ( +/obj/structure/table/reinforced, +/obj/machinery/recharger, +/obj/item/radio/intercom{ + name = "east bump"; + pixel_x = 28 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Nu" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/power/tesla_coil{ + anchored = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"NK" = ( +/obj/structure/table/reinforced, +/obj/machinery/kitchen_machine/microwave, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"NW" = ( +/obj/machinery/light/small{ + dir = 4; + pixel_y = 8 + }, +/obj/structure/closet/emcloset, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Oq" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"OD" = ( +/obj/machinery/computer/secure_data{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"PK" = ( +/obj/machinery/power/port_gen/pacman/upgraded{ + anchored = 1 + }, +/obj/structure/cable{ + d2 = 2; + icon_state = "0-2" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"Qh" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/machinery/door_control{ + id = "mental_health"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_y = -25; + specialfunctions = 4 + }, +/turf/simulated/floor/mineral/silver, +/area/shuttle/escape) +"Qs" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkyellowfull" + }, +/area/shuttle/escape) +"QM" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/rack, +/obj/item/storage/firstaid/regular{ + pixel_x = 5; + pixel_y = 5 + }, +/obj/item/storage/firstaid/regular{ + pixel_x = 6; + pixel_y = -5 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"Rc" = ( +/obj/structure/table/reinforced, +/obj/item/storage/surgical_tray, +/obj/item/stack/nanopaste, +/obj/item/reagent_containers/glass/bottle/reagent/hydrocodone, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Rh" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/bed/roller, +/obj/machinery/iv_drip, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"SQ" = ( +/obj/structure/rack, +/obj/item/storage/toolbox/electrical, +/obj/item/storage/toolbox/mechanical{ + pixel_y = 5 + }, +/obj/item/multitool, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"Tc" = ( +/obj/machinery/sleeper{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + icon_state = "darkblue" + }, +/area/shuttle/escape) +"UY" = ( +/obj/effect/turf_decal/blue_corner{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkbluecorners" + }, +/area/shuttle/escape) +"Vf" = ( +/obj/effect/spawner/window/plastitanium, +/obj/machinery/door/poddoor/preopen{ + id = "ravenbridgeblast"; + name = "Cockpit Blast Door"; + id_tag = "ravenbridgeblast" + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"VM" = ( +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Wk" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Wo" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"Wq" = ( +/obj/effect/turf_decal/delivery/blue/partial{ + dir = 4 + }, +/obj/effect/turf_decal/delivery/blue/partial{ + dir = 8 + }, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"WJ" = ( +/obj/machinery/recharge_station, +/turf/simulated/floor/plasteel/dark, +/area/shuttle/escape) +"WU" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkbluefull" + }, +/area/shuttle/escape) +"Xz" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/turf/simulated/floor/mineral/plastitanium/red, +/area/shuttle/escape) +"XB" = ( +/obj/structure/closet/crate/internals, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/simulated/floor/plating, +/area/shuttle/escape) +"XO" = ( +/obj/structure/closet/secure_closet/engineering_welding, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/shuttle/escape) +"Yi" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellowcorners"; + dir = 4 + }, +/area/shuttle/escape) +"YC" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkblue" + }, +/area/shuttle/escape) +"Zg" = ( +/obj/structure/shuttle/engine/heater, +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/simulated/floor/plating/airless, +/area/shuttle/escape) + +(1,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +Vf +Vf +Vf +Vf +av +jK +iJ +iJ +iJ +fE +hv +av +av +iJ +iJ +iJ +iJ +iJ +"} +(2,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +av +DD +ut +jZ +yM +uW +DD +av +ul +qk +ul +gZ +VM +IF +Je +bm +iJ +iJ +iJ +iJ +"} +(3,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +bO +kO +OD +zb +zb +zb +Iu +Wk +Vf +ul +ul +ul +gZ +VM +NW +Je +dP +iJ +iJ +iJ +iJ +"} +(4,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +lj +kO +rd +UY +UY +UY +Cl +fR +av +av +av +av +av +gS +av +av +av +jK +iJ +iJ +iJ +"} +(5,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +vF +kO +Ko +lH +lH +lH +iY +DZ +av +jn +av +fH +IJ +lH +IJ +wS +av +av +iJ +iJ +iJ +"} +(6,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +av +gZ +av +av +av +gZ +av +jK +iJ +iJ +iJ +av +av +ae +av +xv +wx +vk +av +Qh +av +Tc +WU +WU +WU +yg +nP +av +iJ +iJ +iJ +"} +(7,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +av +av +av +av +av +hv +av +av +eP +UY +eL +av +tW +UY +eL +av +av +gZ +av +av +eP +WU +av +av +Vf +av +av +ii +av +bA +Wk +WU +WU +WU +Jb +av +dP +iJ +iJ +"} +(8,1,1) = {" +iJ +iJ +iJ +jK +av +av +av +gZ +av +av +av +SQ +wu +wF +XB +av +sT +Bn +av +Id +UY +rp +av +Id +UY +rp +av +fL +WJ +fL +av +eP +WU +fL +fL +fL +fL +av +VM +av +KQ +KT +Wk +WU +kr +xI +av +Zg +dP +iJ +"} +(9,1,1) = {" +jK +gZ +hv +av +av +ww +qS +fL +mS +fG +av +lH +lH +lH +lH +av +gS +av +av +HK +WU +lH +eh +lH +WU +nP +av +Oq +WU +WU +av +Nc +WU +lH +lH +lH +lH +jr +YC +dq +WU +Jd +Iu +Iu +Wk +Rc +av +av +IN +dP +"} +(10,1,1) = {" +yD +Wq +Wq +AK +Wq +Wq +Wq +Wq +Wq +Wq +dq +UY +UY +UY +UY +xj +UY +UY +dq +WU +UY +If +Bx +bV +UY +WU +dq +UY +UY +UY +dq +WU +UY +UY +UY +UY +UY +UY +uc +gs +bA +WU +yg +Wk +WU +ob +KL +av +IN +dP +"} +(11,1,1) = {" +jK +gZ +hv +av +av +KB +mS +ku +gX +sE +av +av +gS +av +Iu +Iu +Iu +Iu +av +gN +WU +Iu +EV +Iu +WU +rX +av +CL +WU +KY +av +eP +WU +Nt +NK +HL +Iu +EV +kg +dq +WU +yg +lH +lH +YC +Rc +av +av +IN +dP +"} +(12,1,1) = {" +iJ +iJ +iJ +jK +av +av +av +gZ +av +av +av +Bn +Ky +av +rg +Bi +QM +sx +av +bo +UY +ew +av +bo +UY +ew +av +ku +WJ +ku +av +eP +WU +av +gZ +av +wz +av +gZ +av +Rh +WU +WU +yg +jp +xI +av +qb +dP +iJ +"} +(13,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +av +hv +av +av +av +av +av +av +eP +UY +Ek +av +eP +UY +eL +av +av +gZ +av +av +eP +WU +av +nX +DU +DU +DU +Xz +av +gU +WU +WU +WU +yg +Jb +av +dP +iJ +iJ +"} +(14,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +av +gZ +av +av +av +gZ +av +jK +iJ +iJ +iJ +av +av +ek +av +nX +DU +DU +DU +Xz +av +bQ +WU +WU +WU +Jd +rX +av +iJ +iJ +iJ +"} +(15,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +bO +kO +ok +Yi +av +Hk +it +it +it +HE +av +kZ +of +of +Iu +Nd +av +av +iJ +iJ +iJ +"} +(16,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +lj +kO +XO +hs +av +av +av +av +av +av +av +av +av +gZ +FP +av +av +jK +iJ +iJ +iJ +"} +(17,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +vF +kO +cn +Qs +Qs +pV +gS +Wo +hv +ul +ul +ul +gZ +cF +Kg +Je +bm +iJ +iJ +iJ +iJ +"} +(18,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +av +Mb +PK +AS +Nu +av +IF +av +ul +qk +ul +gZ +yA +mV +Je +dP +iJ +iJ +iJ +iJ +"} +(19,1,1) = {" +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +iJ +jK +av +gZ +gZ +av +av +av +jK +iJ +iJ +iJ +gZ +gZ +gZ +gZ +iJ +iJ +iJ +iJ +iJ +"} diff --git a/_maps/map_files/stations/boxstation.dmm b/_maps/map_files/stations/boxstation.dmm index 412826b1377..01ace0aec76 100644 --- a/_maps/map_files/stations/boxstation.dmm +++ b/_maps/map_files/stations/boxstation.dmm @@ -258,6 +258,10 @@ /obj/item/target, /obj/item/target, /obj/item/target, +/obj/item/target/syndicate, +/obj/item/target/syndicate, +/obj/item/target/syndicate, +/obj/item/target/syndicate, /turf/simulated/floor/plasteel, /area/station/security/range) "acD" = ( @@ -453,7 +457,6 @@ /obj/machinery/camera{ c_tag = "Firing Range" }, -/obj/machinery/syndicatebomb/training, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/security/range) @@ -466,7 +469,7 @@ name = "east bump"; pixel_x = 24 }, -/turf/simulated/floor/plating, +/turf/simulated/floor/plasteel, /area/station/security/range) "adn" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, @@ -522,9 +525,8 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/item/radio/intercom/department/security{ - pixel_y = -28 - }, +/obj/machinery/nuclearbomb/training, +/obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/security/range) "adE" = ( @@ -537,13 +539,34 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/syndicatebomb/training, /turf/simulated/floor/plasteel, /area/station/security/range) "adG" = ( +/obj/item/disk/nuclear/training{ + pixel_y = -2; + pixel_x = -7 + }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 9 }, /obj/effect/decal/cleanable/dirt, +/obj/structure/table/reinforced, +/obj/item/paper/nuclear_guide_spacing{ + pixel_x = 10; + pixel_y = 7 + }, +/obj/item/paper/nuclear_guide_defusing{ + pixel_x = 9; + pixel_y = 4 + }, +/obj/item/disk/nuclear/training{ + pixel_x = -5 + }, +/obj/item/paper/nuclear_guide_operating{ + pixel_x = 8; + pixel_y = 1 + }, /turf/simulated/floor/plasteel, /area/station/security/range) "adH" = ( @@ -1696,10 +1719,22 @@ /area/station/command/office/hos) "aij" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/rack, -/obj/item/target/syndicate, -/obj/item/target/syndicate, -/obj/item/target/syndicate, +/obj/item/storage/toolbox/mechanical{ + pixel_x = 3; + pixel_y = 6 + }, +/obj/item/multitool{ + pixel_y = -5; + pixel_x = 5 + }, +/obj/item/clothing/head/welding{ + pixel_y = -2; + pixel_x = -6 + }, +/obj/structure/table/reinforced, +/obj/item/radio/intercom/department/security{ + pixel_x = 28 + }, /turf/simulated/floor/plasteel, /area/station/security/range) "aio" = ( @@ -11923,7 +11958,6 @@ /area/station/hallway/secondary/entry/north) "aMC" = ( /obj/structure/table, -/obj/machinery/computer/mob_healer_terminal, /turf/simulated/floor/carpet/arcade, /area/station/public/arcade) "aMD" = ( @@ -14876,9 +14910,6 @@ /area/station/medical/reception) "aVy" = ( /obj/machinery/economy/vending/coffee, -/obj/machinery/computer/mob_healer_terminal{ - pixel_x = 28 - }, /obj/structure/sign/poster/official/random{ pixel_y = 32 }, @@ -35301,13 +35332,14 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Laser Room" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /obj/structure/cable{ d1 = 1; d2 = 2; icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /turf/simulated/floor/plating, /area/station/engineering/control) "cmd" = ( @@ -38903,13 +38935,14 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Laser Room" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /obj/structure/cable{ d1 = 1; d2 = 2; icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /turf/simulated/floor/plating, /area/station/engineering/control) "cyS" = ( @@ -52294,12 +52327,6 @@ icon_state = "vault" }, /area/station/engineering/gravitygenerator) -"dCJ" = ( -/obj/structure/transit_tube/cap{ - dir = 8 - }, -/turf/simulated/floor/plating, -/area/station/turret_protected/aisat/interior) "dCM" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -55778,13 +55805,6 @@ icon_state = "darkgreen" }, /area/station/medical/medbay3) -"fes" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/machinery/computer/mob_battle_terminal/red, -/turf/simulated/floor/plasteel, -/area/station/public/dorms) "feN" = ( /turf/simulated/floor/plasteel, /area/station/hallway/secondary/entry/north) @@ -57663,10 +57683,12 @@ layer = 4; pixel_y = 32 }, -/obj/structure/transit_tube/station, /obj/structure/transit_tube_pod{ dir = 4 }, +/obj/structure/transit_tube/station/reverse/flipped{ + dir = 1 + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -64030,9 +64052,6 @@ name = "north bump"; pixel_y = 24 }, -/obj/structure/transit_tube/cap{ - dir = 4 - }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -65342,12 +65361,6 @@ /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, /area/station/supply/lobby) -"jPN" = ( -/obj/machinery/computer/mob_battle_terminal/blue{ - pixel_x = -32 - }, -/turf/simulated/floor/plasteel, -/area/station/public/dorms) "jPZ" = ( /obj/structure/sign/poster/official/cleanliness{ pixel_x = 32 @@ -72410,11 +72423,11 @@ /turf/simulated/floor/plasteel, /area/station/supply/storage) "nrh" = ( -/obj/structure/transit_tube/station, /obj/structure/transit_tube_pod{ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/visible/yellow, +/obj/structure/transit_tube/station/reverse, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior) "nrD" = ( @@ -76992,10 +77005,6 @@ }, /turf/simulated/floor/plating, /area/station/security/permabrig) -"pwU" = ( -/obj/effect/landmark/battle_mob_point, -/turf/simulated/floor/engine, -/area/holodeck/alphadeck) "pxv" = ( /obj/machinery/atmospherics/unary/outlet_injector/on{ dir = 8; @@ -82089,7 +82098,7 @@ id = "engsm"; name = "Radiation Shutters Control"; pixel_y = -24; - req_access_txt = "10" + req_access_txt = "32" }, /obj/effect/turf_decal/stripes/line, /turf/simulated/floor/engine, @@ -131932,7 +131941,7 @@ aab aaa cQp wza -dCJ +dnW dnv dnW diz @@ -132341,7 +132350,7 @@ nXr aKQ fRL aPm -jPN +aPm lkw fho aPm @@ -132590,7 +132599,7 @@ awE ayf azn arR -fes +tbC tbC tbC aPm @@ -133621,10 +133630,10 @@ atG sHt sHt sHt -pwU sHt sHt -pwU +sHt +sHt sHt sHt sHt diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm index 817cd6ed17c..b23ff7503b7 100644 --- a/_maps/map_files/stations/cerestation.dmm +++ b/_maps/map_files/stations/cerestation.dmm @@ -2486,13 +2486,6 @@ /obj/machinery/ai_status_display, /turf/simulated/wall/r_wall, /area/station/turret_protected/aisat/interior) -"apu" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/lootdrop/maintenance, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/fore2) "apw" = ( /obj/structure/table, /obj/item/storage/toolbox/emergency, @@ -2752,37 +2745,41 @@ /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/fpmaint) "ard" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light/small, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 9 }, -/area/station/security/permabrig) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/syndicatebomb/training, +/obj/machinery/light, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "arh" = ( -/obj/item/vending_refill/cola, -/obj/item/multitool, -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/grouped_spawner{ - group_id = "tunnelbats"; - max_per_spawner = 1; - name = "bat spawner"; - path_to_spawn = /mob/living/simple_animal/hostile/scarybat; - total_amount = 20 +/obj/item/disk/nuclear/training{ + pixel_y = -2; + pixel_x = -7 }, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" +/obj/structure/table/reinforced, +/obj/item/paper/nuclear_guide_spacing{ + pixel_x = 10; + pixel_y = 7 }, -/area/station/maintenance/fore2) -"ark" = ( -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" +/obj/item/paper/nuclear_guide_defusing{ + pixel_x = 9; + pixel_y = 4 }, -/area/station/maintenance/fore2) -"arl" = ( -/obj/structure/closet/emcloset, -/turf/simulated/floor/plating, -/area/station/maintenance/fore2) +/obj/item/disk/nuclear/training{ + pixel_x = -5 + }, +/obj/item/paper/nuclear_guide_operating{ + pixel_x = 8; + pixel_y = 1 + }, +/turf/simulated/floor/plasteel{ + icon_state = "redcorner" + }, +/area/station/security/defusal) "arm" = ( /obj/machinery/door/airlock/maintenance{ name = "Fore Asteroid Maintenance Access" @@ -5829,6 +5826,13 @@ "aMC" = ( /turf/simulated/mineral/ancient, /area/station/medical/break_room) +"aME" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plating{ + icon_state = "asteroidplating" + }, +/area/station/security/permabrig) "aMJ" = ( /obj/machinery/firealarm{ dir = 1; @@ -11253,7 +11257,7 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Laser Room" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /obj/structure/cable{ d1 = 1; d2 = 2; @@ -11261,6 +11265,7 @@ }, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -12062,19 +12067,21 @@ pixel_x = -3; pixel_y = -2 }, -/obj/item/clothing/glasses/sunglasses, +/turf/simulated/floor/plasteel, +/area/station/security/range) +"bsP" = ( +/obj/item/radio/intercom{ + pixel_y = -28; + name = "custom placement" + }, +/obj/structure/table/reinforced, /obj/item/clothing/glasses/sunglasses{ pixel_x = 3; pixel_y = 3 }, -/turf/simulated/floor/plasteel, -/area/station/security/range) -"bsP" = ( -/obj/machinery/syndicatebomb/training, -/obj/structure/closet/bombclosetsecurity, -/obj/item/radio/intercom{ - pixel_y = -28; - name = "custom placement" +/obj/item/clothing/glasses/sunglasses, +/obj/item/storage/box/flashbangs{ + pixel_x = -16 }, /turf/simulated/floor/plasteel, /area/station/security/range) @@ -25812,13 +25819,16 @@ /turf/simulated/floor/wood, /area/station/legal/magistrate) "cKZ" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/access/all/security/general, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" +/obj/machinery/atmospherics/unary/vent_scrubber/on, +/obj/item/radio/intercom{ + name = "custom placement"; + pixel_y = 28 }, -/area/station/maintenance/fore2) +/obj/machinery/camera{ + c_tag = "Defusal Workshop" + }, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "cLa" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -28999,6 +29009,23 @@ icon_state = "darkyellow" }, /area/station/engineering/atmos) +"cZi" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 + }, +/obj/structure/cable/orange{ + d2 = 2; + icon_state = "0-2" + }, +/obj/machinery/power/apc/directional/west, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "redcorner" + }, +/area/station/security/defusal) "cZr" = ( /obj/structure/chair{ dir = 8 @@ -29371,13 +29398,11 @@ /area/station/security/prison/cell_block/A) "ddl" = ( /obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable/orange{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/structure/cable/orange, /obj/machinery/door/firedoor, +/obj/structure/cable/orange{ + d2 = 4; + icon_state = "0-4" + }, /turf/simulated/floor/plating, /area/station/security/permabrig) "ddn" = ( @@ -33148,9 +33173,10 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Laser Room" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -33955,6 +33981,17 @@ icon_state = "yellowcorner" }, /area/station/hallway/primary/central/east) +"dEa" = ( +/obj/machinery/light_switch{ + name = "north bump"; + pixel_y = 24 + }, +/obj/machinery/alarm/directional/west, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "redcorner" + }, +/area/station/security/defusal) "dEi" = ( /obj/structure/table/wood, /obj/item/ammo_box/shotgun/beanbag, @@ -34819,6 +34856,24 @@ icon_state = "bluered" }, /area/station/hallway/secondary/entry/west) +"dQG" = ( +/obj/machinery/door/airlock/security/glass{ + name = "Defusal Workshop" + }, +/obj/effect/mapping_helpers/airlock/access/all/security/general, +/obj/machinery/door/firedoor, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "red" + }, +/area/station/security/defusal) "dQR" = ( /obj/machinery/door/airlock/maintenance{ name = "Aft Asteroid Maintenance" @@ -36720,15 +36775,6 @@ /obj/machinery/hologram/holopad, /turf/simulated/floor/plasteel, /area/station/hallway/secondary/exit) -"eAn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/closet/firecloset, -/obj/item/crowbar/red, -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/plating, -/area/station/maintenance/fore2) "eAu" = ( /obj/effect/turf_decal/delivery, /obj/machinery/recharge_station, @@ -41487,6 +41533,25 @@ /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/transparent/glass/reinforced, /area/station/maintenance/apmaint) +"gmV" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 9 + }, +/obj/structure/table/reinforced, +/obj/item/clothing/head/welding{ + pixel_x = 12; + pixel_y = 6 + }, +/obj/item/multitool{ + pixel_x = -4; + pixel_y = 6 + }, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -3; + pixel_y = -2 + }, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "gmZ" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 5 @@ -42842,6 +42907,21 @@ icon_state = "whitebluecorner" }, /area/station/medical/surgery/secondary) +"gLb" = ( +/obj/item/vending_refill/cola, +/obj/item/multitool, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/grouped_spawner{ + group_id = "tunnelbats"; + max_per_spawner = 1; + name = "bat spawner"; + path_to_spawn = /mob/living/simple_animal/hostile/scarybat; + total_amount = 20 + }, +/turf/simulated/floor/plating{ + icon_state = "asteroidplating" + }, +/area/station/security/permabrig) "gLj" = ( /obj/structure/table/wood, /obj/effect/spawner/lootdrop/maintenance/eight, @@ -43849,6 +43929,15 @@ icon_state = "red" }, /area/station/security/storage) +"hcm" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/firecloset, +/obj/item/crowbar/red, +/obj/machinery/light{ + dir = 1 + }, +/turf/simulated/floor/plating, +/area/station/security/permabrig) "hco" = ( /obj/structure/cable/orange{ d1 = 4; @@ -44431,6 +44520,14 @@ /obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) +"hnL" = ( +/obj/machinery/atmospherics/unary/vent_pump/on, +/obj/machinery/firealarm{ + name = "north bump"; + pixel_y = 24 + }, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "hoa" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 6 @@ -50739,12 +50836,12 @@ /turf/simulated/floor/plating, /area/station/hallway/primary/central/west) "jjh" = ( -/obj/structure/cable/orange{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, /obj/effect/decal/cleanable/dirt, +/obj/structure/cable/orange{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/plasteel, /area/station/security/permabrig) "jjp" = ( @@ -53865,20 +53962,6 @@ temperature = 80 }, /area/station/science/xenobiology) -"khV" = ( -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable/orange{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/cable/orange{ - d2 = 8; - icon_state = "0-8" - }, -/obj/machinery/door/firedoor, -/turf/simulated/floor/plating, -/area/station/security/brig) "kic" = ( /obj/structure/closet/wardrobe/grey, /turf/simulated/floor/mineral/titanium/blue, @@ -59525,6 +59608,15 @@ icon_state = "cafeteria" }, /area/station/service/kitchen) +"lQa" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/machinery/door/firedoor, +/obj/structure/cable/orange{ + d2 = 8; + icon_state = "0-8" + }, +/turf/simulated/floor/plating, +/area/station/security/permabrig) "lQy" = ( /obj/machinery/optable, /obj/machinery/light{ @@ -60954,11 +61046,6 @@ /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/plating, /area/station/maintenance/disposal/external/southwest) -"moQ" = ( -/obj/effect/spawner/lootdrop/maintenance, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating, -/area/station/maintenance/fore2) "moY" = ( /obj/structure/closet/secure_closet/medical3, /obj/machinery/light, @@ -62522,15 +62609,6 @@ }, /turf/simulated/floor/plating, /area/station/security/brig) -"mSf" = ( -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable/orange{ - d2 = 8; - icon_state = "0-8" - }, -/obj/machinery/door/firedoor, -/turf/simulated/floor/plating, -/area/station/security/permabrig) "mSh" = ( /obj/structure/girder, /turf/simulated/floor/plating, @@ -62825,13 +62903,12 @@ /turf/simulated/floor/plating, /area/station/maintenance/maintcentral) "mVr" = ( -/obj/item/clothing/shoes/orange, -/obj/item/clothing/under/color/orange/prison, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" +/obj/machinery/nuclearbomb/training, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "redcorner" }, -/area/station/maintenance/fore2) +/area/station/security/defusal) "mVs" = ( /obj/structure/disposalpipe/segment/corner{ dir = 8; @@ -63272,6 +63349,16 @@ /obj/structure/sign/securearea, /turf/simulated/wall, /area/station/engineering/tech_storage) +"nde" = ( +/obj/structure/cable/orange{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, +/turf/simulated/floor/plasteel{ + icon_state = "floorgrime" + }, +/area/station/security/permabrig) "ndl" = ( /obj/effect/spawner/window/reinforced/polarized/grilled{ id = "rd" @@ -65368,6 +65455,11 @@ icon_state = "neutralcorner" }, /area/station/hallway/primary/fore/east) +"nNB" = ( +/obj/effect/spawner/lootdrop/maintenance, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plating, +/area/station/security/permabrig) "nNF" = ( /obj/machinery/door/airlock/maintenance{ name = "Service SMES Access" @@ -65403,6 +65495,10 @@ }, /turf/simulated/floor/plating, /area/station/hallway/primary/port/north) +"nOr" = ( +/obj/structure/closet/emcloset, +/turf/simulated/floor/plating, +/area/station/security/permabrig) "nOu" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/disposalpipe/segment, @@ -69524,6 +69620,9 @@ icon_state = "dark" }, /area/station/turret_protected/ai) +"peU" = ( +/turf/simulated/wall/r_wall, +/area/station/security/defusal) "pfe" = ( /obj/structure/chair/wood{ dir = 1 @@ -77318,6 +77417,30 @@ }, /turf/simulated/floor/plasteel, /area/station/public/locker) +"rGv" = ( +/obj/structure/cable/orange{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/station/security/brig) "rGw" = ( /obj/structure/disposalpipe/segment/corner, /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ @@ -82602,12 +82725,6 @@ icon_state = "whitegreen" }, /area/station/medical/virology) -"tpw" = ( -/obj/effect/landmark/battle_mob_point, -/turf/simulated/floor/engine{ - name = "Holodeck Projector Floor" - }, -/area/holodeck/alphadeck) "tpA" = ( /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -83579,16 +83696,18 @@ /area/station/maintenance/port) "tFL" = ( /obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable/orange{ - d2 = 8; - icon_state = "0-8" - }, -/obj/structure/cable/orange{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/door/firedoor, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/obj/structure/cable/orange, /turf/simulated/floor/plating, /area/station/security/permabrig) "tFY" = ( @@ -91624,6 +91743,14 @@ icon_state = "darkyellow" }, /area/station/engineering/control) +"weh" = ( +/obj/item/clothing/shoes/orange, +/obj/item/clothing/under/color/orange/prison, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plating{ + icon_state = "asteroidplating" + }, +/area/station/security/permabrig) "weN" = ( /obj/structure/cable{ d1 = 4; @@ -92008,6 +92135,13 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/primary/aft/west) +"wiU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/lootdrop/maintenance, +/turf/simulated/floor/plating{ + icon_state = "asteroidplating" + }, +/area/station/security/permabrig) "wiV" = ( /obj/structure/mirror{ pixel_x = -28 @@ -95268,7 +95402,7 @@ id = "engsm"; name = "Radiation Shutters Control"; pixel_y = 24; - req_access_txt = "10" + req_access_txt = "32" }, /obj/machinery/camera{ c_tag = "SM South"; @@ -98581,6 +98715,7 @@ /obj/machinery/light/small{ dir = 4 }, +/obj/structure/closet/bombclosetsecurity, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -116641,10 +116776,10 @@ bEM pDn pDn pDn -tpw pDn pDn -tpw +pDn +pDn pDn pDn pDn @@ -118894,7 +119029,7 @@ rHj cDb rHj aQL -aQL +nde tFL rNK rNK @@ -119152,10 +119287,10 @@ gLk cVR amO myY -tFL +lQa rNK rNK -khV +lPn yfX fOj awv @@ -119409,11 +119544,11 @@ dpC rHj adc rHj -mSf -rNK -rNK -lPn -yfX +peU +peU +peU +peU +wGz uaJ awB uqz @@ -119666,12 +119801,12 @@ rHj rHj vNP sFU -afd -afd -afd -afd -wGz -uaJ +peU +dEa +cZi +dQG +dsy +rGv dtr uqz aLp @@ -119923,10 +120058,10 @@ rHj cgX tkn dqz -tkn -rHj +peU +hnL ard -afd +peU daG sVX daG @@ -120176,13 +120311,13 @@ aTz afd aTz aTz -rHj -aTz -aTz afd afd -cKZ +aME mYJ +peU +cKZ +gmV fqh eBm krP @@ -120433,11 +120568,11 @@ afd afd aTz aTz -aTz -aTz -aTz afd -vXM +tkn +weh +gLb +peU mVr arh fqh @@ -120690,13 +120825,13 @@ abW abW afd aTz -aTz -aTz -aTz afd -eAn -moQ -ark +hcm +nNB +adc +peU +peU +peU fqh xax pZs @@ -120945,15 +121080,15 @@ rNK cRv abW abW -abW +afd +aTz +afd +vNP +wiU +nOr afd aTz aTz -aTz -afd -vrQ -apu -arl asu atc eZh @@ -121202,15 +121337,15 @@ rNK cRv cRv cRv -abW afd aTz aTz -aTz -aTz afd afd aTz +afd +aTz +aTz fqh bOR gyQ diff --git a/_maps/map_files/stations/deltastation.dmm b/_maps/map_files/stations/deltastation.dmm index b9bbeef06f0..0d416241c10 100644 --- a/_maps/map_files/stations/deltastation.dmm +++ b/_maps/map_files/stations/deltastation.dmm @@ -28019,6 +28019,34 @@ icon_state = "neutralfull" }, /area/station/hallway/primary/port/north) +"bDD" = ( +/obj/item/disk/nuclear/training{ + pixel_y = -2; + pixel_x = -7 + }, +/obj/structure/table/reinforced, +/obj/item/paper/nuclear_guide_spacing{ + pixel_x = 10; + pixel_y = 7 + }, +/obj/item/paper/nuclear_guide_defusing{ + pixel_x = 9; + pixel_y = 4 + }, +/obj/item/disk/nuclear/training{ + pixel_x = -5 + }, +/obj/item/paper/nuclear_guide_operating{ + pixel_x = 8; + pixel_y = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/unary/vent_scrubber/on{ + dir = 1 + }, +/obj/machinery/alarm/directional/south, +/turf/simulated/floor/plasteel, +/area/station/security/range) "bDE" = ( /obj/item/kirbyplants, /obj/machinery/status_display{ @@ -35212,7 +35240,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/table, -/obj/machinery/syndicatebomb/training, +/obj/item/toy/figure/crew/secofficer, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -40235,6 +40263,16 @@ /turf/simulated/floor/plasteel, /area/station/security/range) "cju" = ( +/obj/machinery/syndicatebomb/training, +/turf/simulated/floor/plasteel, +/area/station/security/range) +"cjv" = ( +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/simulated/floor/plating, +/area/station/security/range) +"cjw" = ( /obj/structure/table/reinforced, /obj/machinery/recharger{ pixel_x = -6; @@ -40247,27 +40285,8 @@ pixel_x = 7; pixel_y = 3 }, -/obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/plasteel, /area/station/security/range) -"cjv" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plating, -/area/station/security/range) -"cjw" = ( -/obj/structure/sign/securearea{ - pixel_y = 32 - }, -/turf/simulated/floor/plating, -/area/station/security/range) -"cjx" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/plating, -/area/station/security/range) "cjy" = ( /obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/plating, @@ -40863,9 +40882,6 @@ icon_state = "4-8" }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -40901,10 +40917,13 @@ d2 = 8; icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/security/range) "clf" = ( @@ -41413,7 +41432,6 @@ icon_state = "1-2" }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line, /turf/simulated/floor/plasteel, /area/station/security/range) "cmC" = ( @@ -41437,18 +41455,8 @@ /turf/simulated/floor/plating, /area/station/security/range) "cmF" = ( -/obj/structure/table/reinforced, -/obj/machinery/alarm/directional/south, -/obj/item/gun/energy/laser/practice, -/obj/item/gun/energy/laser/practice, -/obj/item/clothing/ears/earmuffs, -/obj/item/clothing/ears/earmuffs, -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, +/obj/machinery/nuclearbomb/training, +/obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/security/range) "cmG" = ( @@ -44275,13 +44283,6 @@ icon_state = "neutralfull" }, /area/station/hallway/primary/starboard/south) -"cut" = ( -/obj/machinery/light, -/obj/structure/sign/securearea{ - pixel_y = -32 - }, -/turf/simulated/floor/plating, -/area/station/security/range) "cuu" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -59862,6 +59863,14 @@ icon_state = "whitebluefull" }, /area/station/maintenance/starboard) +"dxV" = ( +/obj/structure/table/reinforced, +/obj/item/gun/energy/laser/practice, +/obj/item/gun/energy/laser/practice, +/obj/item/clothing/ears/earmuffs, +/obj/item/clothing/ears/earmuffs, +/turf/simulated/floor/plasteel, +/area/station/security/range) "dyb" = ( /turf/simulated/floor/plating, /area/station/maintenance/theatre) @@ -67079,6 +67088,23 @@ /obj/structure/cable, /turf/simulated/floor/plasteel/white, /area/station/science/explab) +"eOg" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/unary/vent_pump/on, +/obj/item/clothing/head/welding{ + pixel_x = 9; + pixel_y = 10 + }, +/obj/item/multitool{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/item/storage/toolbox/mechanical{ + pixel_y = -2; + pixel_x = -3 + }, +/turf/simulated/floor/plasteel, +/area/station/security/range) "eOt" = ( /obj/structure/table/glass, /obj/structure/cable{ @@ -69896,6 +69922,19 @@ dir = 5 }, /area/space/nearstation) +"gAP" = ( +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plasteel, +/area/station/security/range) "gAR" = ( /obj/structure/closet/wardrobe/pjs, /obj/structure/cable{ @@ -80599,7 +80638,6 @@ "ngl" = ( /obj/structure/table, /obj/item/storage/fancy/donut_box, -/obj/item/toy/figure/crew/secofficer, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -87511,9 +87549,6 @@ /area/station/maintenance/starboard) "rjL" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/transit_tube/cap{ - dir = 8 - }, /obj/item/radio/intercom{ name = "south bump"; pixel_y = -28 @@ -92501,7 +92536,8 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/turf/simulated/floor/plating, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plasteel, /area/station/security/range) "tVV" = ( /turf/simulated/floor/plasteel{ @@ -97302,9 +97338,7 @@ /obj/machinery/ai_status_display{ pixel_y = -32 }, -/obj/structure/transit_tube/station{ - dir = 1 - }, +/obj/structure/transit_tube/station/reverse/flipped, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "vault" @@ -152270,9 +152304,9 @@ cgr hFc cgr jIs -cjv -iCU -cjv +eOg +gAP +bDD cjr brS bHF @@ -152529,7 +152563,7 @@ ccL jIs cjw tVO -cjz +dxV cjr eeN lnU @@ -152784,9 +152818,9 @@ ccM ceC cgo jIs -cjx -tVO -cut +cjv +iCU +cjv cjr cpa cqI diff --git a/_maps/map_files/stations/metastation.dmm b/_maps/map_files/stations/metastation.dmm index ca66c423b30..7380ac46420 100644 --- a/_maps/map_files/stations/metastation.dmm +++ b/_maps/map_files/stations/metastation.dmm @@ -806,9 +806,6 @@ /turf/simulated/wall, /area/station/public/arcade) "ajb" = ( -/obj/machinery/computer/mob_battle_terminal/red{ - pixel_y = 30 - }, /obj/item/kirbyplants/plant20, /turf/simulated/floor/plasteel{ icon_state = "darkgrey" @@ -3389,9 +3386,6 @@ name = "east bump"; pixel_x = 27 }, -/obj/machinery/computer/mob_battle_terminal/blue{ - pixel_y = -30 - }, /turf/simulated/floor/plasteel{ icon_state = "darkgrey" }, @@ -8848,7 +8842,7 @@ id = "engsm"; name = "Radiation Shutters Control"; pixel_x = 24; - req_access_txt = "10" + req_access_txt = "32" }, /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -19452,10 +19446,12 @@ /turf/simulated/floor/wood, /area/station/command/office/captain/bedroom) "bsI" = ( -/obj/structure/transit_tube/station, /obj/structure/sign/securearea{ pixel_y = 32 }, +/obj/structure/transit_tube/station/reverse/flipped{ + dir = 1 + }, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "darkbluecorners" @@ -47045,13 +47041,25 @@ /turf/simulated/floor/wood, /area/station/service/bar) "exm" = ( -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" +/obj/machinery/door/airlock/security/glass, +/obj/effect/mapping_helpers/airlock/autoname, +/obj/effect/mapping_helpers/airlock/access/any/security/general, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/turf/simulated/floor/plating, -/area/station/security/main) +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/turf/simulated/floor/plasteel{ + icon_state = "redfull" + }, +/area/station/security/defusal) "exI" = ( /obj/structure/table/glass, /obj/item/hand_labeler, @@ -48607,6 +48615,37 @@ }, /turf/simulated/floor/carpet, /area/station/legal/lawoffice) +"ffH" = ( +/obj/item/disk/nuclear/training{ + pixel_y = -2; + pixel_x = -7 + }, +/obj/item/paper/nuclear_guide_spacing{ + pixel_x = 10; + pixel_y = 7 + }, +/obj/item/paper/nuclear_guide_defusing{ + pixel_x = 9; + pixel_y = 4 + }, +/obj/item/disk/nuclear/training{ + pixel_x = -5 + }, +/obj/item/paper/nuclear_guide_operating{ + pixel_x = 8; + pixel_y = 1 + }, +/obj/structure/table, +/obj/machinery/camera{ + c_tag = "Defusal Workshop" + }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = 24; + name = "east bump" + }, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "fga" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment{ @@ -49977,6 +50016,24 @@ /obj/effect/decal/cleanable/blood, /turf/simulated/floor/bluegrid, /area/station/maintenance/starboard) +"fFo" = ( +/obj/structure/table, +/obj/item/radio/intercom{ + name = "south bump"; + pixel_y = -28 + }, +/obj/item/clothing/head/welding{ + pixel_x = -4; + pixel_y = 19 + }, +/obj/item/multitool{ + pixel_x = 7; + pixel_y = 13 + }, +/obj/item/storage/toolbox/mechanical, +/obj/machinery/alarm/directional/east, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "fFL" = ( /obj/machinery/atmospherics/meter, /obj/machinery/atmospherics/pipe/simple/visible/yellow, @@ -50222,12 +50279,12 @@ /area/station/hallway/primary/central/north) "fJr" = ( /obj/machinery/disposal, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/structure/disposalpipe/trunk, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/plasteel{ icon_state = "darkred" }, @@ -53400,9 +53457,6 @@ /obj/structure/table, /obj/item/stack/medical/bruise_pack, /obj/item/stack/medical/ointment, -/obj/machinery/computer/mob_healer_terminal{ - pixel_y = 30 - }, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "whiteblue" @@ -53831,9 +53885,6 @@ }, /area/station/medical/virology) "hkm" = ( -/obj/structure/transit_tube/cap{ - dir = 4 - }, /obj/machinery/status_display{ layer = 4; pixel_y = 32 @@ -59778,6 +59829,23 @@ "jKj" = ( /turf/simulated/wall/r_wall, /area/station/engineering/ai_transit_tube) +"jKG" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 10 + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "red" + }, +/area/station/security/defusal) "jKP" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -60579,6 +60647,14 @@ }, /turf/simulated/floor/plating, /area/station/medical/virology) +"jXY" = ( +/obj/machinery/nuclearbomb/training, +/obj/machinery/atmospherics/unary/vent_scrubber/on, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "red" + }, +/area/station/security/defusal) "jYj" = ( /obj/machinery/atmospherics/pipe/manifold/visible/cyan{ dir = 8; @@ -66792,7 +66868,7 @@ name = "Supermatter Engine Room" }, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /obj/structure/cable{ d1 = 4; d2 = 8; @@ -66801,6 +66877,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /turf/simulated/floor/plating, /area/station/engineering/control) "mCX" = ( @@ -69551,6 +69628,9 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/simulated/floor/plating, /area/station/engineering/control) +"nEV" = ( +/turf/simulated/wall/r_wall, +/area/station/security/defusal) "nFf" = ( /obj/structure/table/glass, /obj/item/reagent_containers/dropper, @@ -72815,7 +72895,6 @@ name = "Supermatter Engine Room" }, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, /obj/structure/cable{ d1 = 4; d2 = 8; @@ -72824,6 +72903,8 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, +/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos, /turf/simulated/floor/plating, /area/station/engineering/control) "pgs" = ( @@ -79389,6 +79470,21 @@ icon_state = "dark" }, /area/station/security/permabrig) +"rOj" = ( +/obj/machinery/syndicatebomb/training, +/obj/machinery/light_switch{ + dir = 4; + name = "west bump"; + pixel_x = -24 + }, +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "red" + }, +/area/station/security/defusal) "rOp" = ( /obj/machinery/door/airlock/tranquillite{ name = "Old Mime's Storage" @@ -79617,6 +79713,22 @@ icon_state = "whitebluefull" }, /area/station/medical/exam_room) +"rUg" = ( +/obj/structure/table, +/obj/machinery/light{ + dir = 4 + }, +/obj/item/book/manual/wiki/hacking{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/machinery/power/apc/directional/east, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/turf/simulated/floor/plasteel, +/area/station/security/defusal) "rUl" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/simple/heat_exchanging{ @@ -83836,10 +83948,6 @@ icon_state = "cafeteria" }, /area/station/service/kitchen) -"tNe" = ( -/obj/effect/spawner/random_spawners/wall_rusted_probably, -/turf/simulated/wall/r_wall, -/area/station/maintenance/fore) "tNg" = ( /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel{ @@ -88708,15 +88816,6 @@ }, /area/station/medical/surgery/observation) "vVR" = ( -/obj/structure/table, -/obj/item/screwdriver{ - pixel_x = -2; - pixel_y = 18 - }, -/obj/item/wirecutters{ - pixel_y = 5 - }, -/obj/machinery/syndicatebomb/training, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "red" @@ -124925,7 +125024,7 @@ aaa aaa laH aaa -apO +sRw fJr hwP vgv @@ -125183,11 +125282,11 @@ aaa laH abq apO -jSU -apO +nEV +nEV exm -apO -apO +nEV +nEV xyP apO apO @@ -125440,11 +125539,11 @@ aaa aaa aaa laH -aaa -aaa -aaa -aaa -tNe +nEV +jXY +jKG +rOj +nEV oQV ajg jiR @@ -125697,11 +125796,11 @@ aaa aaa aaa laH -aaa -aaa -aaa -aaa -ahH +nEV +ffH +rUg +fFo +nEV alW akR aDY @@ -125954,11 +126053,11 @@ aaa aaa aaa laH -aaa -aaa -aaa -aaa -ahH +nEV +nEV +nEV +nEV +nEV aDY wLB cnV @@ -126216,8 +126315,8 @@ abq abq abq ajg -ajg -aVY +ahH +ahH ajg aWv cXu diff --git a/code/__DEFINES/atmospherics_defines.dm b/code/__DEFINES/atmospherics_defines.dm index fa2355a729f..a9e2c82b71e 100644 --- a/code/__DEFINES/atmospherics_defines.dm +++ b/code/__DEFINES/atmospherics_defines.dm @@ -141,6 +141,9 @@ //LAVALAND #define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland +#define LAVALAND_TEMPERATURE 500 +#define LAVALAND_OXYGEN 8 +#define LAVALAND_NITROGEN 14 // Reactions #define N2O_DECOMPOSITION_MIN_ENERGY 1400 diff --git a/code/__DEFINES/bots.dm b/code/__DEFINES/bots.dm index 83485ff54a2..ff3712ed9c0 100644 --- a/code/__DEFINES/bots.dm +++ b/code/__DEFINES/bots.dm @@ -28,12 +28,13 @@ #define BOT_EAT_TILE 19 // adding said tiles to inventory (floorbots) //Bot types -#define SEC_BOT (1<<0) // Secutritrons (Beepsky) and ED-209s -#define MULE_BOT (1<<1) // MULEbots -#define FLOOR_BOT (1<<2) // Floorbots -#define CLEAN_BOT (1<<3) // Cleanbots -#define MED_BOT (1<<4) // Medibots -#define HONK_BOT (1<<5) // Honkbots +#define SEC_BOT "Security" // Secutritrons (Beepsky) and ED-209s +#define MULE_BOT "Mule" // MULEbots +#define FLOOR_BOT "Floorbot" // Floorbots +#define CLEAN_BOT "Cleanbot" // Cleanbots +#define MED_BOT "Medibot" // Medibots +#define HONK_BOT "Honkbot" // Honkbots +#define GRIEF_BOT "Grief" // Griefsky //Sentience types #define SENTIENCE_ORGANIC 1 diff --git a/code/__DEFINES/combat_defines.dm b/code/__DEFINES/combat_defines.dm index 01e0c8990c7..368e1cb2df4 100644 --- a/code/__DEFINES/combat_defines.dm +++ b/code/__DEFINES/combat_defines.dm @@ -1,7 +1,5 @@ //Damage things //TODO: merge these down to reduce on defines //Way to waste perfectly good damagetype names (BRUTE) on this... If you were really worried about case sensitivity, you could have just used lowertext(damagetype) in the proc... -#define CUT "cut" -#define BRUISE "bruise" #define BRUTE "brute" #define BURN "fire" #define TOX "tox" diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 1d4d33ac264..3dd763ba3da 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -342,6 +342,8 @@ #define COMSIG_MIND_TRANSER_TO "mind_transfer_to" ///called on the mob instead of the mind #define COMSIG_BODY_TRANSFER_TO "body_transfer_to" +///called when the mind is initialized (called every time the mob logins) +#define COMSIG_MIND_INITIALIZE "mind_initialize" // /mob signals @@ -717,9 +719,12 @@ // /obj/item/gun signals -/// called in /obj/item/gun/process_fire (user, target, params, zone_override) -#define COMSIG_MOB_FIRED_GUN "mob_fired_gun" -/// called in /obj/item/gun/process_fire (user, target) +///called in /obj/item/gun/fire_gun (user, target, flag, params) +#define COMSIG_GUN_TRY_FIRE "gun_try_fire" + #define COMPONENT_CANCEL_GUN_FIRE (1<<0) +///called in /obj/item/gun/afterattack (user, target, flag, params) +#define COMSIG_MOB_TRY_FIRE "mob_fired_gun" +///called in /obj/item/gun/process_fire (user, target) #define COMSIG_GUN_FIRED "gun_fired" /// called in /datum/component/automatic_fire/proc/on_mouse_down: (client/clicker, atom/target, turf/location, control, params) #define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown" diff --git a/code/__DEFINES/emotes_defines.dm b/code/__DEFINES/emotes_defines.dm index 9940edab859..f654bb678bb 100644 --- a/code/__DEFINES/emotes_defines.dm +++ b/code/__DEFINES/emotes_defines.dm @@ -57,6 +57,8 @@ #define EMOTE_TARGET_BHVR_RAW 4 /// The emote target should be just a number. Anything else will be rejected. #define EMOTE_TARGET_BHVR_NUM 5 +/// The emote target is used elsewhere, and processing should be skipped. +#define EMOTE_TARGET_BHVR_IGNORE 6 // This set determines the type of target that we want to check for. @@ -75,3 +77,12 @@ /// List of emotes useable by ghosties #define USABLE_DEAD_EMOTES list("*flip", "*spin") + +// Strings used for the rock paper scissors emote and status effect +#define RPS_EMOTE_ROCK "rock" +#define RPS_EMOTE_PAPER "paper" +#define RPS_EMOTE_SCISSORS "scissors" + +#define RPS_EMOTE_THEY_WIN "aww" +#define RPS_EMOTE_WE_WIN "yay" +#define RPS_EMOTE_TIE "tie" diff --git a/code/__DEFINES/food_defines.dm b/code/__DEFINES/food_defines.dm index 83d378400e1..35131425ad7 100644 --- a/code/__DEFINES/food_defines.dm +++ b/code/__DEFINES/food_defines.dm @@ -1,5 +1,13 @@ -// Used for secondary goals. +/// Used for secondary goals. +/// TOO easy, not accepted for variety goals. #define FOOD_GOAL_SKIP 0 +/// Easy food, ask for a lot for single goals. #define FOOD_GOAL_EASY 1 +/// Normal food, ask for a middling amount for single goals. #define FOOD_GOAL_NORMAL 2 +/// Hard reagent, ask for a little for single goals. #define FOOD_GOAL_HARD 3 +/// TOO hard, accepted for variety goals, but never used for single goals. +#define FOOD_GOAL_EXCESSIVE 4 +/// Same as FOOD_GOAL_EXCESSIVE, just different name to indicate that there's another version of this food that's used in variety goals. +#define FOOD_GOAL_DUPLICATE FOOD_GOAL_EXCESSIVE diff --git a/code/__DEFINES/mecha_hides.dm b/code/__DEFINES/mecha_hides.dm new file mode 100644 index 00000000000..3c1c1496a54 --- /dev/null +++ b/code/__DEFINES/mecha_hides.dm @@ -0,0 +1,6 @@ +#define HIDES_COVERED_FULL 3 +#define PLATES_COVERED_FULL 3 + +#define DRAKE_HIDES_COVERED_SLIGHT 1 +#define DRAKE_HIDES_COVERED_MODERATE 2 +#define DRAKE_HIDES_COVERED_FULL 3 diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index 17beb518b37..e3fee8035c7 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -250,6 +250,10 @@ 0.4,0.6,0.0,\ 0.2,0.2,0.6) +#define MATRIX_STANDARD list(1.0,0.0,0.0,\ + 0.0,1.0,0.0,\ + 0.0,0.0,1.0) + /* Used for wire name appearances. Replaces the color name on the left with the one on the right. The color on the left is the one used as the actual color of the wire, but it doesn't look good when written. @@ -398,7 +402,7 @@ #define INVESTIGATE_BOMB "bombs" // The SQL version required by this version of the code -#define SQL_VERSION 55 +#define SQL_VERSION 56 // Vending machine stuff #define CAT_NORMAL (1<<0) diff --git a/code/__DEFINES/mob_defines.dm b/code/__DEFINES/mob_defines.dm index 5d57157cfb4..5c1d026c3ae 100644 --- a/code/__DEFINES/mob_defines.dm +++ b/code/__DEFINES/mob_defines.dm @@ -298,6 +298,7 @@ #define HEALTH_HUD_OVERRIDE_HEALTHY 3 // Eye protection #define FLASH_PROTECTION_VERYVUNERABLE -4 +#define FLASH_PROTECTION_EXTRA_SENSITIVE -2 #define FLASH_PROTECTION_SENSITIVE -1 #define FLASH_PROTECTION_NONE 0 #define FLASH_PROTECTION_FLASH 1 diff --git a/code/__DEFINES/nanomob_defines.dm b/code/__DEFINES/nanomob_defines.dm deleted file mode 100644 index 0e3510e62c3..00000000000 --- a/code/__DEFINES/nanomob_defines.dm +++ /dev/null @@ -1,17 +0,0 @@ -#define NANOMOB_TYPE_FIRE /datum/mob_type/fire -#define NANOMOB_TYPE_WATER /datum/mob_type/water -#define NANOMOB_TYPE_GRASS /datum/mob_type/grass -#define NANOMOB_TYPE_ELECTRIC /datum/mob_type/electric -#define NANOMOB_TYPE_GROUND /datum/mob_type/ground -#define NANOMOB_TYPE_ROCK /datum/mob_type/rock -#define NANOMOB_TYPE_BUG /datum/mob_type/bug -#define NANOMOB_TYPE_POISON /datum/mob_type/poison -#define NANOMOB_TYPE_NORMAL /datum/mob_type/normal -#define NANOMOB_TYPE_FIGHTING /datum/mob_type/fighting -#define NANOMOB_TYPE_PSYCHIC /datum/mob_type/psychic -#define NANOMOB_TYPE_GHOST /datum/mob_type/ghost -#define NANOMOB_TYPE_ICE /datum/mob_type/ice -#define NANOMOB_TYPE_FLYING /datum/mob_type/flying -#define NANOMOB_TYPE_BLUESPACE /datum/mob_type/bluespace -#define NANOMOB_TYPE_DARK /datum/mob_type/dark -#define NANOMOB_TYPE_STEEL /datum/mob_type/steel diff --git a/code/__DEFINES/particle_defines.dm b/code/__DEFINES/particle_defines.dm index b261cd4f98d..e4c0b381bbc 100644 --- a/code/__DEFINES/particle_defines.dm +++ b/code/__DEFINES/particle_defines.dm @@ -5,3 +5,16 @@ #define DEBRIS_GLASS "glass" #define DEBRIS_LEAF "leaf" #define DEBRIS_SNOW "snow" + +/* + * Generator defines + */ + +#define GEN_NUM "num" +#define GEN_VECTOR "vector" +#define GEN_BOX "box" +#define GEN_COLOR "color" +#define GEN_CIRCLE "circle" +#define GEN_SPHERE "sphere" +#define GEN_SQUARE "square" +#define GEN_CUBE "cube" diff --git a/code/__DEFINES/reagents_defines.dm b/code/__DEFINES/reagents_defines.dm index 45bc2fafd1d..25f1b1661a2 100644 --- a/code/__DEFINES/reagents_defines.dm +++ b/code/__DEFINES/reagents_defines.dm @@ -34,7 +34,13 @@ #define BLOOD_TYPE_FAKE_BLOOD "Vh Null" /// Used for secondary goals. +/// TOO easy, not accepted for variety goals. #define REAGENT_GOAL_SKIP 0 +/// Easy reagent, ask for a lot for single goals. #define REAGENT_GOAL_EASY 1 +/// Normal reagent, ask for a middling amount for single goals. #define REAGENT_GOAL_NORMAL 2 +/// Hard reagent, ask for a little for single goals. #define REAGENT_GOAL_HARD 3 +/// TOO hard, accepted for variety goals, but never used for single goals. +#define REAGENT_GOAL_EXCESSIVE 4 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index d34fb486829..9f3b5bb8893 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -178,6 +178,7 @@ #define STATUS_EFFECT_HIGHFIVE /datum/status_effect/high_five #define STATUS_EFFECT_DAP /datum/status_effect/high_five/dap #define STATUS_EFFECT_HANDSHAKE /datum/status_effect/high_five/handshake +#define STATUS_EFFECT_RPS /datum/status_effect/high_five/rps #define STATUS_EFFECT_CHARGING /datum/status_effect/charging diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 335ac141fc8..b213db5ac2d 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -91,7 +91,6 @@ // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) #define FIRE_PRIORITY_PING 10 -#define FIRE_PRIORITY_NANOMOB 10 #define FIRE_PRIORITY_NIGHTSHIFT 10 #define FIRE_PRIORITY_IDLE_NPC 10 #define FIRE_PRIORITY_CLEANUP 10 diff --git a/code/__DEFINES/wires_defines.dm b/code/__DEFINES/wires_defines.dm index ef149154212..c1d1160bbb0 100644 --- a/code/__DEFINES/wires_defines.dm +++ b/code/__DEFINES/wires_defines.dm @@ -46,9 +46,11 @@ #define WIRE_BOMB_ACTIVATE "Activate" // Will start a bombs timer if pulsed, will hint if pulsed while already active, will stop a timer a bomb on cut. // Nuclear bomb -#define WIRE_BOMB_LIGHT "Bomb Light" -#define WIRE_BOMB_TIMING "Bomb Timing" -#define WIRE_BOMB_SAFETY "Bomb Safety" +#define WIRE_NUKE_SAFETY "Safety" +#define WIRE_NUKE_DETONATOR "Detonator" +#define WIRE_NUKE_DISARM "Disarm" +#define WIRE_NUKE_LIGHT "Lights" +#define WIRE_NUKE_CONTROL "Control Panel" // Particle accelerator #define WIRE_PARTICLE_POWER "Power Toggle" // Toggles whether the PA is on or not. diff --git a/code/__DEFINES/zoom.dm b/code/__DEFINES/zoom.dm new file mode 100644 index 00000000000..f36a97019aa --- /dev/null +++ b/code/__DEFINES/zoom.dm @@ -0,0 +1,5 @@ +///How the scope component is toggled. +/// Wielding the object with both hands toggles the zoom. Requires the two-handed component to work. +#define ZOOM_METHOD_WIELD 1 +/// Activated by clicking an item action button specified by the `item_action_type` var. +#define ZOOM_METHOD_ITEM_ACTION 2 diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index aeb341bc7ea..3cb5928179a 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -223,6 +223,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CAN_VIEW_HEALTH "can_view_health" // Also used for /Stat #define TRAIT_MAGPULSE "magnetificent" // Used for anything that is magboot related #define TRAIT_NOSLIP "noslip" +#define TRAIT_SCOPED "user_scoped" #define TRAIT_MEPHEDRONE_ADAPTED "mephedrone_adapted" // Trait that changes the ending effects of twitch leaving your system #define TRAIT_NOKNOCKDOWNSLOWDOWN "noknockdownslowdown" //If this person has this trait, they are not slowed via knockdown, but they can be hit by bullets like a self knockdown #define TRAIT_CAN_STRIP "can_strip" // This mob can strip other mobs. diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 7d9cf49c61f..f918fe47277 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -35,6 +35,9 @@ GLOBAL_LIST_EMPTY(beacons) GLOBAL_LIST_EMPTY(shuttle_caller_list) //list of all communication consoles, comms consoles circuit and AIs, for automatic shuttle calls when there are none. GLOBAL_LIST_EMPTY(tracked_implants) //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented... GLOBAL_LIST_EMPTY(pinpointer_list) //list of all pinpointers. Used to change stuff they are pointing to all at once. +GLOBAL_LIST_EMPTY(nuke_list) //list of (real) nukes +GLOBAL_LIST_EMPTY(syndi_nuke_list) //list of syndicate nukes +GLOBAL_LIST_EMPTY(nad_list) //list of (real) nuclear authentication disks GLOBAL_LIST_EMPTY(nuclear_uplink_list) //list of all existing nuke ops uplinks GLOBAL_LIST_EMPTY(abductor_equipment) //list of all abductor equipment GLOBAL_LIST_EMPTY(global_intercoms) //list of all intercomms, across all z-levels diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 4bd180b8222..2e1fc13f5db 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -88,6 +88,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FORCED_STANDING" = TRAIT_FORCED_STANDING, "TRAIT_NOSLIP" = TRAIT_NOSLIP, "TRAIT_MAGPULSE" = TRAIT_MAGPULSE, + "TRAIT_SCOPED" = TRAIT_SCOPED, "TRAIT_MEPHEDRONE_ADAPTED" = TRAIT_MEPHEDRONE_ADAPTED, "TRAIT_NOKNOCKDOWNSLOWDOWN" = TRAIT_NOKNOCKDOWNSLOWDOWN, "TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index 36082679a21..9a22a2b2891 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -239,6 +239,8 @@ GLOBAL_LIST_EMPTY(radial_menus) return else next_check = world.time + check_delay + // if you're wondering why your radial menus aren't clickable while debugging: + // it's probably the stoplag call here, try it again without any breakpoints stoplag(1) /datum/radial_menu/Destroy() diff --git a/code/controllers/subsystem/SSeconomy.dm b/code/controllers/subsystem/SSeconomy.dm index c261d7f963a..8e6e428e69b 100644 --- a/code/controllers/subsystem/SSeconomy.dm +++ b/code/controllers/subsystem/SSeconomy.dm @@ -68,6 +68,7 @@ SUBSYSTEM_DEF(economy) var/credits_per_easy_food_goal = 300 var/credits_per_normal_food_goal = 450 var/credits_per_hard_food_goal = 600 + var/credits_per_variety_food_goal = 450 var/credits_per_ripley_goal = 600 var/credits_per_kudzu_goal = 600 /// credits lost for sending unsecured cargo diff --git a/code/controllers/subsystem/SSnano_mob_hunter.dm b/code/controllers/subsystem/SSnano_mob_hunter.dm deleted file mode 100644 index 93e622f3ae1..00000000000 --- a/code/controllers/subsystem/SSnano_mob_hunter.dm +++ /dev/null @@ -1,155 +0,0 @@ -SUBSYSTEM_DEF(mob_hunt) - name = "Nano-Mob Hunter GO Server" - priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact. - flags = SS_NO_INIT - offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed." - cpu_display = SS_CPUDISPLAY_LOW - var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this - var/list/normal_spawns = list() - var/max_trap_spawns = 15 //change this to adjust the number of trap spawns that can exist at one time. traps spawned beyond this point clear the oldest traps - var/list/trap_spawns = list() - var/list/connected_clients = list() - var/server_status = 1 //1 is online, 0 is offline - var/reset_cooldown = 0 //number of controller cycles before the manual_reboot proc can be used again (ignored if server is offline so you can always boot back up) - var/obj/machinery/computer/mob_battle_terminal/red_terminal - var/obj/machinery/computer/mob_battle_terminal/blue_terminal - var/battle_turn = null - -/datum/controller/subsystem/mob_hunt/fire(resumed = FALSE) - if(reset_cooldown) //if reset_cooldown is set (we are on cooldown, duh), reduce the remaining cooldown every cycle - reset_cooldown-- - if(!server_status) - return - client_mob_update() - if(length(normal_spawns) < max_normal_spawns) - spawn_mob() - -//leaving this here in case admins want to use it for a random mini-event or something -/datum/controller/subsystem/mob_hunt/proc/server_crash(recover_time = 3000) - server_status = 0 - for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients) - client.disconnect("Server Crash") - for(var/obj/effect/nanomob/N in trap_spawns) - N.despawn() - for(var/obj/effect/nanomob/N in normal_spawns) - N.despawn() - //just in case - normal_spawns.Cut() - trap_spawns.Cut() - connected_clients.Cut() - if(!isnum(recover_time)) - recover_time = 3000 - if(recover_time > 0) //when provided with a negative or zero valued recover_time argument, the server won't auto-restart but can be manually rebooted still - //set a timer to automatically recover after recover_time has passed (can be manually restarted if you get impatient too) - addtimer(CALLBACK(src, PROC_REF(auto_recover)), recover_time, TIMER_UNIQUE) - -/datum/controller/subsystem/mob_hunt/proc/client_mob_update() - var/list/ex_players = list() - for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients) - var/mob/living/carbon/human/H = client.get_player() - if(connected_clients[client]) - if(!H || H != connected_clients[client]) - ex_players |= connected_clients[client] - connected_clients[client] = H - if(length(ex_players)) //to make sure we don't do this if we didn't lose any player since the last update - for(var/obj/effect/nanomob/N in (normal_spawns + trap_spawns)) - N.conceal(ex_players) - -/datum/controller/subsystem/mob_hunt/proc/auto_recover() - if(server_status != 0) - return - server_status = 1 - while(length(normal_spawns) < max_normal_spawns) //repopulate the server's spawns completely if we auto-recover from crash - spawn_mob() - -/datum/controller/subsystem/mob_hunt/proc/manual_reboot() - if(server_status && reset_cooldown) - return 0 - for(var/obj/effect/nanomob/N in trap_spawns) - N.despawn() - for(var/obj/effect/nanomob/N in normal_spawns) - N.despawn() - server_status = 1 - reset_cooldown = 25 //25 controller cycle cooldown for manual restarts - return 1 - -/datum/controller/subsystem/mob_hunt/proc/spawn_mob() - var/list/nanomob_types = subtypesof(/datum/mob_hunt) - var/datum/mob_hunt/mob_info = pick(nanomob_types) - new mob_info() - -/datum/controller/subsystem/mob_hunt/proc/register_spawn(datum/mob_hunt/mob_info) - if(!mob_info) - return 0 - var/obj/effect/nanomob/new_mob = new /obj/effect/nanomob(mob_info.spawn_point, mob_info) - normal_spawns += new_mob - new_mob.reveal() - return 1 - -/datum/controller/subsystem/mob_hunt/proc/register_trap(datum/mob_hunt/mob_info) - if(!mob_info) - return 0 - if(!mob_info.is_trap) - return register_spawn(mob_info) - var/obj/effect/nanomob/new_mob = new /obj/effect/nanomob(mob_info.spawn_point, mob_info) - trap_spawns += new_mob - new_mob.reveal() - if(length(trap_spawns) > max_trap_spawns) - var/obj/effect/nanomob/old_trap = trap_spawns[1] - old_trap.despawn() - return 1 - -/datum/controller/subsystem/mob_hunt/proc/start_check() - if(battle_turn) //somehow we got called mid-battle, so lets just stop now - return - if(red_terminal && red_terminal.ready && blue_terminal && blue_terminal.ready) - battle_turn = pick("Red", "Blue") - red_terminal.atom_say("Battle starting!") - blue_terminal.atom_say("Battle starting!") - if(battle_turn == "Red") - red_terminal.atom_say("Red Player's Turn!") - else if(battle_turn == "Blue") - blue_terminal.atom_say("Blue Player's Turn!") - -/datum/controller/subsystem/mob_hunt/proc/launch_attack(team, raw_damage, datum/mob_type/attack_type) - if(!team || !raw_damage) - return - var/obj/machinery/computer/mob_battle_terminal/target = null - if(team == "Red") - target = blue_terminal - else if(team == "Blue") - target = red_terminal - else - return - target.receive_attack(raw_damage, attack_type) - -/datum/controller/subsystem/mob_hunt/proc/end_battle(loser, surrender = 0) - var/obj/machinery/computer/mob_battle_terminal/winner_terminal = null - var/obj/machinery/computer/mob_battle_terminal/loser_terminal = null - if(loser == "Red") - loser_terminal = red_terminal - winner_terminal = blue_terminal - else if(loser == "Blue") - loser_terminal = blue_terminal - winner_terminal = red_terminal - battle_turn = null - winner_terminal.ready = FALSE - loser_terminal.ready = FALSE - if(surrender) //surrender doesn't give exp, to avoid people just farming exp without actually doing a battle - winner_terminal.atom_say("Your rival surrendered!") - else - var/progress_message = winner_terminal.mob_info.gain_exp() - winner_terminal.atom_say("[winner_terminal.team] Player wins!") - winner_terminal.atom_say(progress_message) - -/datum/controller/subsystem/mob_hunt/proc/end_turn() - red_terminal.updateUsrDialog() - blue_terminal.updateUsrDialog() - if(!battle_turn) - return - if(battle_turn == "Red") - battle_turn = "Blue" - blue_terminal.atom_say("Blue's turn.") - else if(battle_turn == "Blue") - battle_turn = "Red" - blue_terminal.atom_say("Red's turn.") diff --git a/code/controllers/subsystem/SSshuttles.dm b/code/controllers/subsystem/SSshuttles.dm index 5e5a92bdb05..c8492e22ee5 100644 --- a/code/controllers/subsystem/SSshuttles.dm +++ b/code/controllers/subsystem/SSshuttles.dm @@ -38,6 +38,8 @@ SUBSYSTEM_DEF(shuttle) var/custom_escape_shuttle_loading = FALSE /// Whether or not a shuttle is currently being loaded at the template landmark, if it exists. var/loading_shuttle_at_preview_template = FALSE + /// Have we locked in the emergency shuttle, to prevent people from breaking things / wasting player money? + var/emergency_locked_in = FALSE /datum/controller/subsystem/shuttle/Initialize() if(!emergency) @@ -316,6 +318,8 @@ SUBSYSTEM_DEF(shuttle) if(loading_shuttle_at_preview_template) CRASH("A shuttle was already loading at the preview template when another was loaded") + S.preload() + loading_shuttle_at_preview_template = TRUE var/turf/landmark_turf = get_turf(locate("landmark*Shuttle Import")) S.load(landmark_turf, centered = TRUE) @@ -377,6 +381,8 @@ SUBSYSTEM_DEF(shuttle) timer = emergency.timer mode = emergency.mode dock = emergency.get_docked() + if(!dock) //lance moment + dock = getDock("emergency_away") else dock = loaded_shuttle.findRoundstartDock() diff --git a/code/datums/action.dm b/code/datums/action.dm index eb6a1a19005..0a099de316c 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -78,6 +78,8 @@ /datum/action/proc/Trigger(left_click = TRUE) if(!IsAvailable()) return FALSE + if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) + return FALSE return TRUE /datum/action/proc/AltTrigger() @@ -570,7 +572,6 @@ var/obj/item/clothing/shoes/magboots/gravity/G = target G.dash(usr) - ///prset for organ actions /datum/action/item_action/organ_action check_flags = AB_CHECK_CONSCIOUS diff --git a/code/datums/components/debris.dm b/code/datums/components/debris.dm index fd1f058fa79..57bd8c8e32f 100644 --- a/code/datums/components/debris.dm +++ b/code/datums/components/debris.dm @@ -3,35 +3,6 @@ * Originally from https://github.com/tgstation/TerraGov-Marine-Corps/pull/12752 */ -/particles/debris - icon = 'icons/effects/particles/generic_particles.dmi' - width = 500 - height = 500 - count = 10 - spawning = 10 - lifespan = 0.5 SECONDS - fade = 0.3 SECONDS - drift = generator("circle", 0, 7) - scale = 0.3 - velocity = list(50, 0) - friction = generator("num", 0.1, 0.15) - spin = generator("num", -20, 20) - -/particles/impact_smoke - icon = 'icons/effects/effects.dmi' - icon_state = "smoke" - width = 500 - height = 500 - count = 20 - spawning = 20 - lifespan = 0.8 SECONDS - fade = 10 SECONDS - grow = 0.1 - scale = 0.2 - spin = generator("num", -20, 20) - velocity = list(50, 0) - friction = generator("num", 0.1, 0.5) - /datum/component/debris /// Icon state of debris when impacted by a projectile var/debris @@ -76,7 +47,7 @@ if(debris && P.damage_type == BRUTE) debris_visuals = new(parent, /particles/debris) - debris_visuals.particles.position = generator("circle", position_offset, position_offset) + debris_visuals.particles.position = generator(GEN_CIRCLE, position_offset, position_offset) debris_visuals.particles.velocity = list(x_component, y_component) debris_visuals.layer = ABOVE_OBJ_LAYER + 0.02 debris_visuals.particles.icon_state = debris diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index cfd4da69ce1..d5c479bd945 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -262,6 +262,9 @@ current_windup_reduction = (current_windup_reduction + round(autofire_shot_delay * windup_autofire_reduction_multiplier)) timerid = addtimer(CALLBACK(src, PROC_REF(windup_reset), FALSE), windup_spindown, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) + if(shooter.next_move_modifier) //DNA vault, mephemdrone, bluespace slowness debuff. + next_delay = round(next_delay * shooter.next_move_modifier, SSprojectiles.wait) + COOLDOWN_START(src, next_shot_cd, next_delay) if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, allow_akimbo, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) diff --git a/code/datums/components/scope.dm b/code/datums/components/scope.dm new file mode 100644 index 00000000000..0763330d752 --- /dev/null +++ b/code/datums/components/scope.dm @@ -0,0 +1,273 @@ +///A component that allows players to use the item to zoom out. Mainly intended for firearms, but now works with other items too. +/datum/component/scope + /// How far the view can be moved from the player. At 1, it can be moved by the player's view distance; other values scale linearly. + var/range_modifier = 1 + /// Fullscreen object we use for tracking. + var/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/tracker + /// The owner of the tracker's ckey. For comparing with the current owner mob, in case the client has left it (e.g. ghosted). + var/tracker_owner_ckey + /// The method which we zoom in and out + var/zoom_method = ZOOM_METHOD_ITEM_ACTION + /// if not null, an item action will be added. Redundant if the mode is ZOOM_METHOD_RIGHT_CLICK or ZOOM_METHOD_WIELD. + var/item_action_type + /// Time to scope up, if you want the scope to take time to boot up. Used by the LWAP + var/time_to_scope + /// Do we let the user scope and click on the middle of their screen? + var/allow_middle_click = FALSE + /// Do we have the scope cancel on move? + var/movement_cancels_scope = FALSE + +/datum/component/scope/Initialize(range_modifier = 1, zoom_method = ZOOM_METHOD_ITEM_ACTION, item_action_type = /datum/action/zoom, time_to_scope = 0, allow_middle_click = FALSE, movement_cancels_scope = FALSE) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + src.range_modifier = range_modifier + src.zoom_method = zoom_method + src.item_action_type = item_action_type + src.time_to_scope = time_to_scope + src.allow_middle_click = allow_middle_click + src.movement_cancels_scope = movement_cancels_scope + + +/datum/component/scope/Destroy(force) + if(is_zoomed_in()) + stop_zooming(tracker.owner) + return ..() + +/datum/component/scope/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) //Checks for being removed for person, not mob movement + if(zoom_method == ZOOM_METHOD_WIELD) + RegisterSignal(parent, SIGNAL_ADDTRAIT(TRAIT_WIELDED), PROC_REF(on_wielded)) + RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_WIELDED), PROC_REF(on_unwielded)) + if(item_action_type) + var/obj/item/parent_item = parent + var/datum/action/scope = new item_action_type(parent) + parent_item.actions += scope + RegisterSignal(scope, COMSIG_ACTION_TRIGGER, PROC_REF(on_action_trigger)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + if(istype(parent, /obj/item/gun)) + RegisterSignal(parent, COMSIG_GUN_TRY_FIRE, PROC_REF(on_gun_fire)) + +/datum/component/scope/UnregisterFromParent() + if(item_action_type) + var/obj/item/parent_item = parent + var/datum/action/scope = locate(item_action_type) in parent_item.actions + parent_item.actions -= scope + UnregisterSignal(parent, list( + COMSIG_MOVABLE_MOVED, + SIGNAL_ADDTRAIT(TRAIT_WIELDED), + SIGNAL_REMOVETRAIT(TRAIT_WIELDED), + COMSIG_GUN_TRY_FIRE, + COMSIG_PARENT_EXAMINE, + )) + +/datum/component/scope/process() + var/mob/user_mob = tracker.owner + var/client/user_client = user_mob.client + if(!user_client) + stop_zooming(user_mob) + return + tracker.calculate_params() + animate(user_client, world.tick_lag, pixel_x = tracker.given_x, pixel_y = tracker.given_y) + +/datum/component/scope/proc/on_move(atom/movable/source, atom/oldloc, dir, forced) + SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED + + if(!is_zoomed_in()) + return + if(source.loc != tracker.owner) //Dropped. + to_chat(tracker.owner, "[parent]'s scope is overloaded by movement and shuts down!") + stop_zooming(tracker.owner) + +/datum/component/scope/proc/on_action_trigger(datum/action/source) + SIGNAL_HANDLER // COMSIG_ACTION_TRIGGER + var/obj/item/item = source.target + var/mob/living/user = item.loc + if(is_internal_organ(item)) + var/obj/item/organ/internal/O = item + user = O.owner + if(is_zoomed_in()) + stop_zooming(user) + else + INVOKE_ASYNC(src, PROC_REF(zoom), user) + +/datum/component/scope/proc/on_wielded(obj/item/source, trait) + SIGNAL_HANDLER // SIGNAL_ADDTRAIT(TRAIT_WIELDED) + var/mob/living/user = source.loc + INVOKE_ASYNC(src, PROC_REF(zoom), user) + +/datum/component/scope/proc/on_unwielded(obj/item/source, trait) + SIGNAL_HANDLER // SIGNAL_REMOVETRAIT(TRAIT_WIELDED) + var/mob/living/user = source.loc + stop_zooming(user) + +/datum/component/scope/proc/on_gun_fire(obj/item/gun/source, mob/living/user, atom/target, flag, params) + SIGNAL_HANDLER // COMSIG_GUN_TRY_FIRE + if(!tracker?.given_turf || target == get_target(tracker.given_turf)) + return NONE + INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, afterattack), get_target(tracker.given_turf), user) + return COMPONENT_CANCEL_GUN_FIRE + +/datum/component/scope/proc/on_examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER // COMSIG_PARENT_EXAMINE + + var/scope = istype(parent, /obj/item/gun) ? "scope in" : "zoom out" + switch(zoom_method) + if(ZOOM_METHOD_WIELD) + examine_list += "You can [scope] by wielding it with both hands." + +/** + * We find and return the best target to hit on a given turf. + * + * Arguments: + * * target_turf: The turf we are looking for targets on. +*/ +/datum/component/scope/proc/get_target(turf/target_turf) + var/list/non_dense_targets = list() + for(var/atom/movable/possible_target in target_turf) + if(possible_target.layer <= PROJECTILE_HIT_THRESHHOLD_LAYER) + continue + if(possible_target.invisibility > tracker.owner.see_invisible) + continue + if(!possible_target.mouse_opacity) + continue + if(iseffect(possible_target)) + continue + if(ismob(possible_target)) + if(possible_target == tracker.owner) + continue + return possible_target + if(!possible_target.density) + non_dense_targets += possible_target + continue + return possible_target + if(length(non_dense_targets)) + return non_dense_targets[1] + return target_turf + +/** + * We start zooming by adding our tracker overlay and starting our processing. + * + * Arguments: + * * user: The mob we are starting zooming on. +*/ +/datum/component/scope/proc/zoom(mob/user) + if(isnull(user.client)) + return + if(HAS_TRAIT(user, TRAIT_SCOPED)) + to_chat(user, "You are already zoomed in!") + return + if(time_to_scope) + if(!do_after_once(user, time_to_scope, target = parent)) + return + user.playsound_local(parent, 'sound/weapons/scope.ogg', 75, TRUE) + tracker = user.overlay_fullscreen("scope", /atom/movable/screen/fullscreen/stretch/cursor_catcher/scope, istype(parent, /obj/item/gun)) + tracker.assign_to_mob(user, range_modifier) + if(movement_cancels_scope) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + if(allow_middle_click) + RegisterSignal(tracker, COMSIG_CLICK, PROC_REF(generic_click)) + tracker_owner_ckey = user.ckey + if(user.is_holding(parent)) + RegisterSignals(user, list(COMSIG_CARBON_SWAP_HANDS, COMSIG_PARENT_QDELETING), PROC_REF(stop_zooming)) + else // The item is likely worn. + RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(stop_zooming)) + var/static/list/capacity_signals = list( + COMSIG_LIVING_STATUS_PARALYSE, + COMSIG_LIVING_STATUS_STUN, + ) + RegisterSignals(user, capacity_signals, PROC_REF(on_incapacitated)) + START_PROCESSING(SSprojectiles, src) + ADD_TRAIT(user, TRAIT_SCOPED, "[UID(src)]") + if(istype(parent, /obj/item/gun)) + var/obj/item/gun/G = parent + G.on_scope_success(user) + return TRUE + +/datum/component/scope/proc/on_incapacitated(mob/living/source, amount = 0, ignore_canstun = FALSE) + SIGNAL_HANDLER // COMSIG_LIVING_STATUS_PARALYSE, COMSIG_LIVING_STATUS_STUN + + if(amount > 0) + stop_zooming(source) + +/datum/component/scope/proc/generic_click(/obj/source, location, control, params) + SIGNAL_HANDLER // COMSIG_CLICK + INVOKE_ASYNC(tracker.owner, TYPE_PROC_REF(/mob, ClickOn), get_target(tracker.given_turf), params) + +/** + * We stop zooming, canceling processing, resetting stuff back to normal and deleting our tracker. + * + * Arguments: + * * user: The mob we are canceling zooming on. +*/ +/datum/component/scope/proc/stop_zooming(mob/user) + SIGNAL_HANDLER // COMSIG_CARBON_SWAP_HANDS, COMSIG_PARENT_QDELETING + + if(!HAS_TRAIT(user, TRAIT_SCOPED)) + return + + STOP_PROCESSING(SSprojectiles, src) + UnregisterSignal(user, list( + COMSIG_LIVING_STATUS_PARALYSE, + COMSIG_LIVING_STATUS_STUN, + COMSIG_CARBON_SWAP_HANDS, + COMSIG_PARENT_QDELETING, + )) + REMOVE_TRAIT(user, TRAIT_SCOPED, "[UID(src)]") + + user.playsound_local(parent, 'sound/weapons/scope.ogg', 75, TRUE, frequency = -1) + user.clear_fullscreen("scope") + + // if the client has ended up in another mob, find that mob so we can fix their cursor + var/mob/true_user + if(user.ckey != tracker_owner_ckey) + true_user = get_mob_by_ckey(tracker_owner_ckey) + + if(!isnull(true_user)) + user = true_user + + if(user.client) + animate(user.client, 0.2 SECONDS, pixel_x = 0, pixel_y = 0) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + QDEL_NULL(tracker) + tracker_owner_ckey = null + if(istype(parent, /obj/item/gun)) + var/obj/item/gun/G = parent + G.on_scope_end(user) + +/datum/component/scope/proc/is_zoomed_in() + return !!tracker + +/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope + icon = 'icons/mob/screen_scope.dmi' + icon_state = "scope" + /// Multiplier for given_X an given_y. + var/range_modifier = 1 + +/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/assign_to_mob(mob/new_owner, range_modifier) + src.range_modifier = range_modifier + return ..() + +/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/Click(location, control, params) + if(usr == owner) + calculate_params() + SEND_SIGNAL(src, COMSIG_CLICK, location, control, params) + + return ..() + +/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/calculate_params() + var/list/modifiers = params2list(mouse_params) + var/icon_x = text2num(LAZYACCESS(modifiers, "vis-x")) + if(isnull(icon_x)) + icon_x = text2num(LAZYACCESS(modifiers, "icon-x")) + var/icon_y = text2num(LAZYACCESS(modifiers, "vis-y")) + if(isnull(icon_y)) + icon_y = text2num(LAZYACCESS(modifiers, "icon-y")) + given_x = round(range_modifier * (icon_x - view_list[1] * world.icon_size / 2)) + given_y = round(range_modifier * (icon_y - view_list[2] * world.icon_size / 2)) + given_turf = locate(owner.x + round(given_x / world.icon_size, 1), owner.y + round(given_y / world.icon_size, 1), owner.z) + + +/datum/action/zoom + name = "Toggle Scope" + check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING + button_icon_state = "sniper_zoom" diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 01e94bffe15..5b159ce5e2c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -951,6 +951,14 @@ log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") + else if(href_list["editreagents"]) + if(!check_rights(R_DEBUG|R_ADMIN)) + return + + var/atom/A = locateUID(href_list["editreagents"]) + + try_open_reagent_editor(A) + else if(href_list["explode"]) if(!check_rights(R_DEBUG|R_EVENT)) return diff --git a/code/datums/elements/shatters_when_thrown.dm b/code/datums/elements/shatters_when_thrown.dm index 441d365e58c..d8e3aec4273 100644 --- a/code/datums/elements/shatters_when_thrown.dm +++ b/code/datums/elements/shatters_when_thrown.dm @@ -35,7 +35,7 @@ /// Handles the actual shattering part, throwing shards of whatever is defined on the component everywhere /datum/element/shatters_when_thrown/proc/shatter(atom/movable/source, atom/hit_atom) - var/generator/scatter_gen = generator("circle", 0, 48, NORMAL_RAND) + var/generator/scatter_gen = generator(GEN_CIRCLE, 0, 48, NORMAL_RAND) var/scatter_turf = get_turf(hit_atom) for(var/obj/item/scattered_item as anything in source.contents) diff --git a/code/datums/emote.dm b/code/datums/emote.dm index fb1dbb66722..50e70232a35 100644 --- a/code/datums/emote.dm +++ b/code/datums/emote.dm @@ -147,16 +147,16 @@ * * Arguments: * * user - Person that is trying to send the emote. - * * params - Parameters added after the emote. + * * emote_arg - String parameter added after the emote. * * type_override - Override to the current emote_type. * * intentional - Bool that says whether the emote was forced (FALSE) or not (TRUE). * * Returns TRUE if it was able to run the emote, FALSE otherwise. */ -/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE) +/datum/emote/proc/run_emote(mob/user, emote_arg, type_override, intentional = FALSE) . = TRUE var/msg = select_message_type(user, message, intentional) - if(params && message_param) + if(emote_arg && message_param) // In this case, we did make some changes to the message that will be used, and we want to add the postfix on with the new parameters. // This is applicable to things like mimes, who this lets have a target on their canned emote responses. // Note that we only do this if we would otherwise have a message param, meaning there should be some target by default. @@ -164,17 +164,17 @@ if(message_param == EMOTE_PARAM_USE_POSTFIX || (msg != message && message_postfix)) if(!message_postfix) CRASH("Emote was specified to use postfix but message_postfix is empty.") - msg = select_param(user, params, "[remove_ending_punctuation(msg)] [message_postfix]", msg) + msg = select_param(user, emote_arg, "[remove_ending_punctuation(msg)] [message_postfix]", msg) else if(msg == message) // In this case, we're not making any substitutions in select_message_type, but we do have some params we want to sub in. - msg = select_param(user, params, message_param, message) + msg = select_param(user, emote_arg, message_param, message) // If this got propogated up, jump out. if(msg == EMOTE_ACT_STOP_EXECUTION) return TRUE if(isnull(msg)) - to_chat(user, "'[params]' isn't a valid parameter for [key].") + to_chat(user, "'[emote_arg]' isn't a valid parameter for [key].") return TRUE msg = replace_pronoun(user, msg) @@ -230,13 +230,13 @@ * Try to run an emote, checking can_run_emote once before executing the emote itself. * * * user - User of the emote - * * params - Params of the emote to be passed to run_emote + * * params - An optional extra argument included after the emote key. * * type_override - emote type to override the existing one with, if given. * * intentional - Whether or not the emote was triggered intentionally (if false, the emote was forced by code). * * Returns TRUE if the emote was able to be run (or failed successfully), or FALSE if the emote is unusable. */ -/datum/emote/proc/try_run_emote(mob/user, params, type_override, intentional = FALSE) +/datum/emote/proc/try_run_emote(mob/user, emote_arg, type_override, intentional = FALSE) // You can use this signal to block execution of emotes from components/other sources. var/sig_res = SEND_SIGNAL(user, COMSIG_MOB_PREEMOTE, key, intentional) switch(sig_res) @@ -245,9 +245,18 @@ if(COMPONENT_BLOCK_EMOTE_SILENT) return TRUE - . = run_emote(user, params, type_override, intentional) + . = run_emote(user, emote_arg, type_override, intentional) // safeguard in case these get modified + reset_emote() + +/** + * Reset the emote back to its original state. + * Necessary if you've made modifications to the emote itself over the course of its + * execution, as emotes are singletons, and changes would be reflected on every usage of the emote. + */ +/datum/emote/proc/reset_emote() + SHOULD_CALL_PARENT(TRUE) message = initial(message) message_param = initial(message_param) @@ -421,6 +430,9 @@ */ /datum/emote/proc/select_param(mob/user, params, substitution, base_message) + if(target_behavior == EMOTE_TARGET_BHVR_IGNORE) + return base_message + if(target_behavior == EMOTE_TARGET_BHVR_RAW) return replacetext(substitution, "%t", params) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5bde8280239..26d4ba5fa50 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1786,6 +1786,7 @@ //Initialisation procs /mob/proc/mind_initialize() + SHOULD_CALL_PARENT(TRUE) if(mind) mind.key = key else @@ -1797,6 +1798,7 @@ if(!mind.name) mind.name = real_name mind.current = src + SEND_SIGNAL(src, COMSIG_MIND_INITIALIZE) //HUMAN /mob/living/carbon/human/mind_initialize() diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 230aef4f95f..6b481b09daa 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -50,7 +50,20 @@ /datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) //to be overriden for toggling internals, id binding, access etc - return + SHOULD_CALL_PARENT(TRUE) + if(visualsOnly) + return + + if(H.mind) + on_mind_initialize(H) + return + RegisterSignal(H, COMSIG_MIND_INITIALIZE, PROC_REF(on_mind_initialize)) + +// Guaranteed access to mind, will never be called if visualsOnly = TRUE +/datum/outfit/proc/on_mind_initialize(mob/living/carbon/human/H) + SIGNAL_HANDLER // COMSIG_MIND_INITIALIZE + SHOULD_CALL_PARENT(TRUE) + UnregisterSignal(H, COMSIG_MIND_INITIALIZE) // prevent this call from being called multiple times on a human /datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE) pre_equip(H, visualsOnly) diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index 0c8bb8c0d82..217b9658c0a 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -3,21 +3,15 @@ /datum/outfit/admin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) . = ..() - if(!visualsOnly && H.mind) - H.mind.assigned_role = name - H.job = name - -/datum/outfit/admin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) - . = ..() - if(visualsOnly) return - if(H.mind) - H.mind.offstation_role = TRUE - else - H.RegisterSignal(H, COMSIG_HUMAN_LOGIN, TYPE_PROC_REF(/mob/living/carbon/human, apply_offstation_roles)) + H.job = name +/datum/outfit/admin/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + H.mind.assigned_role = name + H.mind.offstation_role = TRUE /proc/apply_to_card(obj/item/card/id/I, mob/living/carbon/human/H, list/access = list(), rank, special_icon) if(!istype(I) || !istype(H)) @@ -1250,17 +1244,17 @@ if(istype(I)) apply_to_card(I, H, get_all_accesses(), "Ancient One", "data") - if(H.mind) - if(!H.mind.has_antag_datum(/datum/antagonist/vampire)) - H.mind.make_vampire(TRUE) - var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire) - V.bloodusable = 9999 - V.bloodtotal = 9999 - V.add_subclass(SUBCLASS_ANCIENT, FALSE) - H.dna.SetSEState(GLOB.jumpblock, TRUE) - singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED) - H.update_mutations() - H.gene_stability = 100 +/datum/outfit/admin/ancient_vampire/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + H.mind.make_vampire() + var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire) + V.bloodusable = 9999 + V.bloodtotal = 9999 + V.add_subclass(SUBCLASS_ANCIENT, FALSE) + H.dna.SetSEState(GLOB.jumpblock, TRUE) + singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED) + H.update_mutations() + H.gene_stability = 100 /datum/outfit/admin/wizard name = "Blue Wizard" @@ -1490,10 +1484,6 @@ H.real_name = "Unknown" //Enforcers sacrifice their name to Oblivion for their power - for(var/spell_path in spell_paths) - var/S = new spell_path - H.mind.AddSpell(S) - var/obj/item/clothing/suit/hooded/oblivion/robes = H.wear_suit if(istype(robes)) robes.ToggleHood() @@ -1502,6 +1492,12 @@ if(istype(I)) apply_to_card(I, H, get_all_accesses(), "Oblivion Enforcer") +/datum/outfit/admin/enforcer/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + for(var/spell_path in spell_paths) + var/S = new spell_path + H.mind.AddSpell(S) + /datum/outfit/admin/viper name = "Solar Federation Viper Infiltrator" diff --git a/code/datums/particles.dm b/code/datums/particles.dm new file mode 100644 index 00000000000..2162198a05c --- /dev/null +++ b/code/datums/particles.dm @@ -0,0 +1,105 @@ +/* + MARK: Impact debris + smoke +*/ + +/particles/debris + icon = 'icons/effects/particles/generic_particles.dmi' + width = 500 + height = 500 + count = 10 + spawning = 10 + lifespan = 0.5 SECONDS + fade = 0.3 SECONDS + drift = generator(GEN_CIRCLE, 0, 7) + scale = 0.3 + velocity = list(50, 0) + friction = generator(GEN_NUM, 0.1, 0.15) + spin = generator(GEN_NUM, -20, 20) + +/particles/impact_smoke + icon = 'icons/effects/effects.dmi' + icon_state = "smoke" + width = 500 + height = 500 + count = 20 + spawning = 20 + lifespan = 0.8 SECONDS + fade = 10 SECONDS + grow = 0.1 + scale = 0.2 + spin = generator(GEN_NUM, -20, 20) + velocity = list(50, 0) + friction = generator(GEN_NUM, 0.1, 0.5) + +/* + MARK: Explosion smoke +*/ + +/particles/explosion_smoke + icon = 'icons/effects/96x96.dmi' + icon_state = "smoke3" + width = 1000 + height = 1000 + count = 45 + spawning = 45 + gradient = list("#FA9632", "#C3630C", "#333333", "#808080", "#FFFFFF") + lifespan = 2.5 SECONDS + fade = 2 SECONDS + color = generator(GEN_NUM, 0, 0.25) + color_change = generator(GEN_NUM, 0.04, 0.05) + velocity = generator(GEN_CIRCLE, 15, 15) + drift = generator(GEN_CIRCLE, 0, 1, NORMAL_RAND) + spin = generator(GEN_NUM, -20, 20) + friction = generator(GEN_NUM, 0.1, 0.5) + gravity = list(1, 2) + scale = 0.25 + grow = 0.05 + +/particles/explosion_smoke/deva + scale = 0.5 + velocity = generator(GEN_CIRCLE, 23, 23) + +/particles/explosion_smoke/small + count = 15 + spawning = 15 + scale = 0.25 + velocity = generator(GEN_CIRCLE, 10, 10) + +/particles/smoke_wave + icon = 'icons/effects/96x96.dmi' + icon_state = "smoke3" + width = 750 + height = 750 + count = 75 + spawning = 75 + lifespan = 3 SECONDS + fade = 6 SECONDS + gradient = list("#BA9F6D", "#808080", "#FFFFFF") + color = generator(GEN_NUM, 0, 0.25) + color_change = generator(GEN_NUM, 0.08, 0.07) + velocity = generator(GEN_CIRCLE, 15, 15) + rotation = generator(GEN_NUM, -45, 45) + scale = 0.15 + grow = 0.05 + friction = 0.1 + +/particles/smoke_wave/small + count = 45 + spawning = 45 + scale = 0.05 + lifespan = 2 SECONDS + fade = 5 SECONDS + +/particles/sparks_outwards + icon = 'icons/effects/64x64.dmi' + icon_state = "flare" + width = 750 + height = 750 + count = 40 + spawning = 20 + lifespan = 5 SECONDS + fade = 2 SECONDS + position = generator(GEN_SPHERE, 8, 8) + velocity = generator(GEN_CIRCLE, 30, 30) + scale = 0.1 + friction = 0.1 diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 239a71da0a7..98ccb16f1ea 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -224,3 +224,11 @@ suffix = "lavaland_surface_watcher_grave.dmm" cost = 5 allow_duplicates = FALSE + +/datum/map_template/ruin/lavaland/shuttlecrash + name = "Crashed Passenger Shuttle" + id = "shuttlecrash" + description = "A passenger shuttle crashsite of indeterminate origin." + suffix = "lavaland_surface_shuttlecrash.dmm" + cost = 5 + allow_duplicates = FALSE diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index a848d94a8bc..c8f79bfcf12 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -8,6 +8,9 @@ var/description var/admin_notes +/datum/map_template/shuttle/proc/preload() + return + /datum/map_template/shuttle/New() if(port_id && suffix) shuttle_id = "[port_id]_[suffix]" @@ -125,6 +128,43 @@ description = "Guaranteed to get you somewhere FAST. With a custom-built plasma engine, this bad boy will put more distance between you and certain danger than any other!" admin_notes = "The aft of the ship has a plasma tank that starts ignited. May get released by crew. The plasma windows next to the engine heaters will also erupt into flame, and also risk getting released by crew." +/datum/map_template/shuttle/emergency/lance + suffix = "lance" + name = "The Lance Crew Evacuation System" + description = "A brand new shuttle by Nanotrasen's finest in shuttle-engineering, it's designed to tactically slam into a destroyed station, \ + dispatching threats and saving crew at the same time! \ + Be careful to stay out of it's path. Comes with a beacon to choose where it docks!" + admin_notes = "WARNING: This shuttle is designed to crash into the station. It has turrets, similar to the raven. Place down the beacon please. Once the shuttle is loaded, it cannot be unloaded." + +/datum/map_template/shuttle/emergency/lance/preload() + message_admins("Preloading [name]!") + var/obj/docking_port/stationary/CCport + CCport = SSshuttle.getDock("emergency_away") + CCport.setDir(4) + CCport.forceMove(locate(136, 107, 1)) + CCport.height = 50 + CCport.dheight = 0 + CCport.width = 19 + CCport.dwidth = 9 + var/obj/docking_port/stationary/CCtransit + CCtransit = SSshuttle.getDock("emergency_transit") + CCtransit.setDir(2) + CCtransit.forceMove(locate(113, 68, 1)) + CCtransit.height = 50 + CCtransit.dheight = 0 + CCtransit.width = 19 + CCtransit.dwidth = 9 + var/obj/docking_port/stationary/syndicate + syndicate = SSshuttle.getDock("emergency_syndicate") + syndicate.setDir(8) + syndicate.forceMove(locate(202, 199, 1)) + syndicate.height = 50 + syndicate.dheight = 0 + syndicate.width = 19 + syndicate.dwidth = 9 + qdel(SSshuttle.getDock("emergency_home"), TRUE) + SSshuttle.emergency_locked_in = TRUE + /datum/map_template/shuttle/ferry/base suffix = "base" name = "transport ferry" diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 1a0339564de..659dbf242dd 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -69,6 +69,20 @@ user.remove_status_effect(type) highfived.remove_status_effect(type) +/datum/status_effect/high_five/proc/wiz_effect(mob/living/carbon/user, mob/living/carbon/highfived) + user.status_flags |= GODMODE + highfived.status_flags |= GODMODE + explosion(get_turf(user), 5, 2, 1, 3, cause = id) + // explosions have a spawn so this makes sure that we don't get gibbed + addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, highfived), 0.3 SECONDS) // I want to be sure this lasts long enough, with lag. + add_attack_logs(user, highfived, "caused a wizard [id] explosion") + +/datum/status_effect/high_five/proc/post_start() + return + +/datum/status_effect/high_five/proc/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived) + user.visible_message("[user.name] and [highfived.name] [success]") + /datum/status_effect/high_five/on_apply() if(!iscarbon(owner)) return FALSE @@ -82,25 +96,23 @@ continue if(is_wiz && iswizard(C)) user.visible_message("[user.name] and [C.name] [critical_success]") - user.status_flags |= GODMODE - C.status_flags |= GODMODE - explosion(get_turf(user), 5, 2, 1, 3, cause = id) - // explosions have a spawn so this makes sure that we don't get gibbed - addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, C), 0.3 SECONDS) //I want to be sure this lasts long enough, with lag. - add_attack_logs(user, C, "caused a wizard [id] explosion") + wiz_effect(user, C) both_wiz = TRUE user.do_attack_animation(C, no_effect = TRUE) C.do_attack_animation(user, no_effect = TRUE) playsound(user, sound_effect, 80) if(!both_wiz) - user.visible_message("[user.name] and [C.name] [success]") + regular_effect(user, C) user.remove_status_effect(type) C.remove_status_effect(type) return FALSE + // We can return to break out of the loop here so we don't auto-remove (which causes the timer on the wizard highfive to break) + // This is safe because we only pass the continue if we don't have the status effect return TRUE // DO NOT AUTOREMOVE owner.custom_emote(EMOTE_VISIBLE, request) owner.create_point_bubble_from_path(item_path, FALSE) + post_start() /datum/status_effect/high_five/on_timeout() owner.visible_message("[owner] [get_missed_message()]") @@ -144,6 +156,96 @@ return pick(missed_messages) +/datum/status_effect/high_five/rps + id = "rps" + critical_success = "both play rock -- THEY'RE GOING IN FOR THE FISTBUMP!" + success = "play rock-paper-scissors!" + sound_effect = 'sound/effects/glassknock.ogg' + request = "wants to play rock-paper-scissors!" + item_path = /obj/item/claymore // it's time to d-d-d-d-d-d-d-duel! + /// The move that you'll be making. + var/move + +/datum/status_effect/high_five/rps/get_missed_message() + var/list/missed_messages = list( + "just seems to be practicing against [owner.p_themselves()]. [owner.p_are(TRUE)] [owner.p_they()] losing?", + "seems more interested in a thumb war." + ) + + return pick(missed_messages) + +/datum/status_effect/high_five/rps/proc/get_move_status(my_move, their_move) + if(my_move == their_move) + return RPS_EMOTE_TIE + switch(my_move) + if(RPS_EMOTE_ROCK) + return their_move == RPS_EMOTE_SCISSORS ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN + + if(RPS_EMOTE_PAPER) + return their_move == RPS_EMOTE_ROCK ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN + + if(RPS_EMOTE_SCISSORS) + return their_move == RPS_EMOTE_PAPER ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN + + else + CRASH("Unknown emote rock type") + +/datum/status_effect/high_five/rps/post_start() + playsound(owner, 'sound/effects/glassknock.ogg', 50, FALSE) + +/datum/status_effect/high_five/rps/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived) + var/datum/status_effect/high_five/rps/their_status_effect = highfived.has_status_effect(type) + var/outcome = get_move_status(move, their_status_effect.move) + var/outcome_msg + switch(outcome) + if(RPS_EMOTE_TIE) + outcome_msg = "It's a tie!" + if(RPS_EMOTE_WE_WIN) + outcome_msg = "[user] wins!" + if(RPS_EMOTE_THEY_WIN) + outcome_msg = "[highfived] wins!" + + user.visible_message( + "[user] plays [move], and [highfived] plays [their_status_effect.move].", + "[highfived] plays [their_status_effect.move].", + "It sounds like rock-paper-scissors." + ) + + user.visible_message( + "[outcome_msg]", + blind_message = "It sounds like [pick(user, highfived)] won!" // you're blind how are you supposed to know + ) + +/datum/status_effect/high_five/rps/on_creation(mob/living/new_owner, made_move) + if(made_move) + if(!(made_move in list(RPS_EMOTE_ROCK, RPS_EMOTE_PAPER, RPS_EMOTE_SCISSORS))) + stack_trace("RPS emote was given an invalid move type on creation.") + else + move = made_move + + return ..() + +/datum/status_effect/high_five/rps/on_apply() + if(!isnull(move)) + to_chat(owner, "You prepare to play [move].") + return ..() // we already have the move, probably from the emote passing it in + + move = get_rock_paper_scissors_move(owner) + if(move == null) + return FALSE // make it auto-remove itself + + to_chat(owner, "You prepare to play [move].") + return ..() + + +/proc/get_rock_paper_scissors_move(mob/living/carbon/user) + var/list/move_icons = list( + RPS_EMOTE_SCISSORS = image(icon = 'icons/obj/items.dmi', icon_state = "bscissor"), + RPS_EMOTE_PAPER = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "paper"), + RPS_EMOTE_ROCK = image(icon = 'icons/obj/toy.dmi', icon_state = "pet_rock") + ) + return show_radial_menu(user, user, move_icons) + /// A status effect that can have a certain amount of "bonus" duration added, which extends the duration every tick, /// although there is a maximum amount of bonus time that can be active at any given time. /datum/status_effect/limited_bonus @@ -218,26 +320,11 @@ tick_interval = 4 /// The number of people the gun has locked on to. Caps at 10 for sanity. var/locks = 0 - /// What direction the owner was in when using the scope. - var/owner_dir = 0 - -/datum/status_effect/lwap_scope/on_creation(mob/living/new_owner, stored_dir = 0) - owner_dir = stored_dir - return ..() /datum/status_effect/lwap_scope/tick() locks = 0 - var/turf/owner_turf = get_turf(owner) - var/scope_turf - for(var/turf/T in RANGE_EDGE_TURFS(7, owner_turf)) - if(get_dir(owner, T) != owner_dir) - continue - if(T in range(owner, 6)) - continue - scope_turf = T - break - if(scope_turf) - for(var/mob/living/L in range(10, scope_turf)) + for(var/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/our_scope in owner.client.screen) + for(var/mob/living/L in range(10, our_scope.given_turf)) if(locks >= LWAP_LOCK_CAP) return if(L == owner || L.stat == DEAD || isslime(L) || ismonkeybasic(L)) //xenobio moment diff --git a/code/datums/uplink_items/uplink_general.dm b/code/datums/uplink_items/uplink_general.dm index 9f8b899c38c..8fe7955fed5 100644 --- a/code/datums/uplink_items/uplink_general.dm +++ b/code/datums/uplink_items/uplink_general.dm @@ -133,11 +133,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) if(limited_stock > 0) limited_stock-- log_game("[key_name(user)] purchased [name]. [name] was discounted to [cost].") + user.create_log(MISC_LOG, "Uplink purchase: [name] was discounted to [cost]tc") if(!user.mind.special_role) message_admins("[key_name_admin(user)] purchased [name] (discounted to [cost]), as a non antagonist.") else log_game("[key_name(user)] purchased [name].") + user.create_log(MISC_LOG, "Uplink purchase: [name] for [cost]tc") if(!user.mind.special_role) message_admins("[key_name_admin(user)] purchased [name], as a non antagonist.") @@ -603,7 +605,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/device_tools/bonerepair name = "Prototype Nanite Autoinjector" - desc = "Stolen prototype full body repair nanites. On injection it will shut down body systems as it revitilizes limbs and organs." + desc = "Stolen prototype full body repair nanites. On injection it will shut down body systems as it revitilizes limbs and organs. Heals organics organs, cybernetic organs, and limbs to fully operational conditions." reference = "NCAI" item = /obj/item/reagent_containers/hypospray/autoinjector/nanocalcium cost = 10 @@ -853,6 +855,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/autosurgeon/organ/syndicate/razorwire cost = 20 +/datum/uplink_item/cyber_implants/scope_eyes + name = "Hardened Kaleido Optics Eyes Autoimplanter" + desc = "These cybernetic eye implants will let you zoom in on far away objects. \ + Many users find it disorienting, and find it hard to interact with things near them when active. \ + This pair has been hardened for special operations personnel." + reference = "KOE" + item = /obj/item/autosurgeon/organ/syndicate/scope_eyes + cost = 20 + + // POINTLESS BADASSERY /datum/uplink_item/badass diff --git a/code/datums/wires/nuclearbomb_wires.dm b/code/datums/wires/nuclearbomb_wires.dm index c997e183d7c..0fe19c82952 100644 --- a/code/datums/wires/nuclearbomb_wires.dm +++ b/code/datums/wires/nuclearbomb_wires.dm @@ -1,11 +1,12 @@ /datum/wires/nuclearbomb holder_type = /obj/machinery/nuclearbomb + labelled = TRUE randomize = TRUE - wire_count = 7 // 3 actual, 4 duds. + wire_count = 5 proper_name = "Nuclear bomb" /datum/wires/nuclearbomb/New(atom/_holder) - wires = list(WIRE_BOMB_LIGHT, WIRE_BOMB_TIMING, WIRE_BOMB_SAFETY) + wires = list(WIRE_NUKE_SAFETY, WIRE_NUKE_DETONATOR, WIRE_NUKE_DISARM, WIRE_NUKE_LIGHT, WIRE_NUKE_CONTROL) return ..() /datum/wires/nuclearbomb/interactable(mob/user) @@ -18,39 +19,64 @@ . = ..() var/obj/machinery/nuclearbomb/N = holder . += "The device is [N.timing ? "shaking!" : "still."]" - . += "The device is [N.safety ? "quiet" : "whirring"]." - . += "The lights are [N.lighthack ? "static" : "functional"]." + . += "The control panel is [is_cut(WIRE_NUKE_CONTROL) ? "turned off" : "functional"]." + . += "The disarm controls are [is_cut(WIRE_NUKE_DISARM) || is_cut(WIRE_NUKE_CONTROL) ? "disabled" : "functional"]." + . += "The safety controls are [is_cut(WIRE_NUKE_SAFETY) || is_cut(WIRE_NUKE_CONTROL) ? "disabled" : "functional"]." + . += "The lights are [is_cut(WIRE_NUKE_LIGHT) ? "static" : "functional"]." /datum/wires/nuclearbomb/on_pulse(wire) var/obj/machinery/nuclearbomb/N = holder switch(wire) - if(WIRE_BOMB_LIGHT) - N.lighthack = !N.lighthack - addtimer(CALLBACK(N, TYPE_PROC_REF(/obj/machinery/nuclearbomb, reset_lighthack_callback)), 10 SECONDS) + if(WIRE_NUKE_SAFETY) + if(!is_cut(WIRE_NUKE_CONTROL)) + N.audible_message("The safety controls flicker.", hearing_distance = 1) - if(WIRE_BOMB_TIMING) + if(WIRE_NUKE_DETONATOR) if(N.timing) - message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonation wire, causing it to explode (JMP)") + if(!N.training) + message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonator wire, causing it to explode (JMP)") N.explode() + else + N.audible_message("[N] whirrs ominously.", hearing_distance = 1) - if(WIRE_BOMB_SAFETY) - N.safety = !N.safety - addtimer(CALLBACK(N, TYPE_PROC_REF(/obj/machinery/nuclearbomb, reset_safety_callback)), 10 SECONDS) + if(WIRE_NUKE_DISARM) + if(N.timing && is_cut(WIRE_NUKE_CONTROL)) + if(!is_cut(WIRE_NUKE_LIGHT)) + N.icon_state = N.sprite_prefix + "nuclearbomb1" + N.timing = FALSE + N.audible_message("The timer on [N] stops!", hearing_distance = 1) + N.update_icon(UPDATE_OVERLAYS) + if(!N.training) + GLOB.bomb_set = FALSE + if(!N.is_syndicate && !N.training) + SSsecurity_level.set_level(N.previous_level) + else if(N.timing && !is_cut(WIRE_NUKE_CONTROL)) + N.audible_message("The disarm controls flash with an error. You need to disable the control panel first!", hearing_distance = 1) + else if(!is_cut(WIRE_NUKE_CONTROL)) + N.audible_message("The disarm controls flicker.", hearing_distance = 1) + + if(WIRE_NUKE_LIGHT) + N.audible_message("The lights on [N] flicker.", hearing_distance = 1) + flick(N.sprite_prefix + "nuclearbombc", N) + + if(WIRE_NUKE_CONTROL) + N.audible_message("[N]'s control panel flickers.", hearing_distance = 1) /datum/wires/nuclearbomb/on_cut(wire, mend) var/obj/machinery/nuclearbomb/N = holder switch(wire) - if(WIRE_BOMB_SAFETY) - if(N.timing) - message_admins("[key_name_admin(usr)] cut a nuclear bomb's timing wire, causing it to explode (JMP)") + if(WIRE_NUKE_DETONATOR) + if(N.timing && !mend) + if(!N.training) + message_admins("[key_name_admin(usr)] cut a nuclear bomb's detonator wire, causing it to explode (JMP)") N.explode() - if(WIRE_BOMB_TIMING) - if(!N.lighthack) - if(N.icon_state == "nuclearbomb2") - N.icon_state = "nuclearbomb1" - N.timing = FALSE - GLOB.bomb_set = FALSE - - if(WIRE_BOMB_LIGHT) - N.lighthack = !N.lighthack + if(WIRE_NUKE_LIGHT) + if(!mend) + N.icon_state = N.sprite_prefix + "nuclearbomb0" + if(mend) + if(N.timing) + N.icon_state = N.sprite_prefix + "nuclearbomb2" + else + N.icon_state = N.sprite_prefix + "nuclearbomb1" + N.update_icon(UPDATE_OVERLAYS) diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 58fc524c8c0..662b9ed349a 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -2,6 +2,8 @@ /datum/wires /// TRUE if the wires will be different every time a new wire datum is created. var/randomize = FALSE + /// TRUE if the wires are labelled for every user + var/labelled = FALSE /// The atom the wires belong too. For example: an airlock. var/atom/holder /// The holder type; used to make sure that the holder is the correct type. @@ -104,7 +106,8 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(eyes && HAS_TRAIT(H, TRAIT_COLORBLIND)) // Check if the human has colorblindness. + var/obj/item/clothing/glasses/glasses = H.get_item_by_slot(SLOT_HUD_GLASSES) + if(eyes && HAS_TRAIT(H, TRAIT_COLORBLIND) && (!glasses || !glasses.correct_wires)) // Check if the human has colorblindness. replace_colors = eyes.replace_colours // Get the colorblind replacement colors list. var/list/wires_list = list() @@ -281,6 +284,8 @@ var/can_probably_see_wires = FALSE var/obj/item/held_item = user.get_active_hand() var/obj/item/offhand = user.get_inactive_hand() + if(labelled) + can_probably_see_wires = TRUE if(istype(held_item) && HAS_TRAIT(held_item, TRAIT_SHOW_WIRE_INFO)) can_probably_see_wires = TRUE if(istype(offhand) && HAS_TRAIT(offhand, TRAIT_SHOW_WIRE_INFO)) diff --git a/code/game/area/ss13_areas/security_areas.dm b/code/game/area/ss13_areas/security_areas.dm index 4729423116c..fc465472ee6 100644 --- a/code/game/area/ss13_areas/security_areas.dm +++ b/code/game/area/ss13_areas/security_areas.dm @@ -106,6 +106,10 @@ name = "\improper Firing Range" icon_state = "firingrange" +/area/station/security/defusal + name = "\improper Defusal Workshop" + icon_state = "defusal" + // Checkpoints /area/station/security/checkpoint diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 5a7fd8a98a0..7b85b1d2b30 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1164,6 +1164,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons) if(curturf) .["Jump to turf"] = "?_src_=holder;adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]" .["Add reagent"] = "?_src_=vars;addreagent=[UID()]" + .["Edit reagents"] = "?_src_=vars;editreagents=[UID()]" .["Trigger explosion"] = "?_src_=vars;explode=[UID()]" .["Trigger EM pulse"] = "?_src_=vars;emp=[UID()]" diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 29bc7c1900a..67973ec313b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -199,7 +199,8 @@ Moved(old_loc, direction, TRUE) /atom/movable/Move(atom/newloc, direct = 0, movetime) - if(!loc || !newloc) return 0 + if(!loc || !newloc) + return FALSE var/atom/oldloc = loc if(loc != newloc) @@ -321,7 +322,7 @@ Moved(old_loc, NONE) - return 1 + return TRUE /atom/movable/proc/onTransitZ(old_z,new_z) for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care. @@ -348,36 +349,36 @@ //Called whenever an object moves and by mobs when they attempt to move themselves through space //And when an object or action applies a force on src, see newtonian_move() below -//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting -//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm +//return FALSE to have src start/keep drifting in a no-grav area and TRUE to stop/not start drifting +//Mobs should return TRUE if they should be able to move of their own volition, see client/Move() in mob_movement.dm //movement_dir == 0 when stopping or any dir when trying to move /atom/movable/proc/Process_Spacemove(movement_dir = 0) if(has_gravity(src)) - return 1 + return TRUE if(pulledby && !pulledby.pulling) - return 1 + return TRUE if(throwing) - return 1 + return TRUE if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier - return 1 + return TRUE - return 0 + return FALSE /atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity if(!loc || Process_Spacemove(0)) inertia_dir = 0 - return 0 + return FALSE inertia_dir = direction if(!direction) - return 1 + return TRUE inertia_last_loc = loc SSspacedrift.processing[src] = src - return 1 + return TRUE //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum) @@ -397,7 +398,7 @@ /atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, dodgeable = TRUE, block_movement = TRUE) if(!target || (flags & NODROP) || speed <= 0) - return 0 + return FALSE if(pulledby) pulledby.stop_pulling() @@ -500,8 +501,8 @@ last_move = buckled_mob.last_move inertia_dir = last_move buckled_mob.inertia_dir = last_move - return 0 - return 1 + return FALSE + return TRUE /atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) return FALSE @@ -521,7 +522,7 @@ /atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5) if(mover in buckled_mobs) - return 1 + return TRUE return ..() /atom/movable/proc/get_spacemove_backup() diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 29124ecc503..0d48b4f514e 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -339,8 +339,6 @@ ~~~~~~~~~~~~~~~~~~~~~*/ /obj/mecha/proc/diag_hud_set_mechhealth() var/image/holder = hud_list[DIAG_MECH_HUD] - var/icon/I = icon(icon, icon_state, dir) - holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "huddiag[RoundDiagBar(obj_integrity/max_integrity)]" /obj/mecha/proc/diag_hud_set_mechcell() diff --git a/code/game/dna/mutations/monkey_mutation.dm b/code/game/dna/mutations/monkey_mutation.dm index 18334b1bd91..d1c4d7f960b 100644 --- a/code/game/dna/mutations/monkey_mutation.dm +++ b/code/game/dna/mutations/monkey_mutation.dm @@ -29,18 +29,17 @@ H.set_species(has_primitive_form, keep_missing_bodyparts = TRUE) new /obj/effect/temp_visual/monkeyify(H.loc) - sleep(22) + addtimer(CALLBACK(src, PROC_REF(finish_monkeyize), H, !has_primitive_form), 2.2 SECONDS) +/datum/mutation/monkey/proc/finish_monkeyize(mob/living/carbon/human/H, should_gib) H.invisibility = initial(H.invisibility) - if(!has_primitive_form) //If the pre-change mob in question has no primitive set, this is going to be messy. + if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy. H.gib() return REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT) to_chat(H, "You are now a [H.dna.species.name].") - return H - /datum/mutation/monkey/deactivate(mob/living/carbon/human/H) ..() if(!istype(H)) @@ -63,11 +62,13 @@ H.set_species(has_greater_form, keep_missing_bodyparts = TRUE) new /obj/effect/temp_visual/monkeyify/humanify(H.loc) - sleep(22) + addtimer(CALLBACK(src, PROC_REF(finish_unmonkeyize), H, !has_greater_form), 2.2 SECONDS) + +/datum/mutation/monkey/proc/finish_unmonkeyize(mob/living/carbon/human/H, should_gib) REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT) H.invisibility = initial(H.invisibility) - if(!has_greater_form) //If the pre-change mob in question has no primitive set, this is going to be messy. + if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy. H.gib() return @@ -76,4 +77,3 @@ to_chat(H, "You are now a [H.dna.species.name].") - return H diff --git a/code/game/dna/mutations/mutation_powers.dm b/code/game/dna/mutations/mutation_powers.dm index 0c974c59d64..d25a11adfd7 100644 --- a/code/game/dna/mutations/mutation_powers.dm +++ b/code/game/dna/mutations/mutation_powers.dm @@ -394,6 +394,9 @@ return var/atom/movable/the_item = targets[1] + if(!user.Adjacent(the_item)) + to_chat(user, "You need to be next to [the_item] for this!") + return FALSE if(ishuman(the_item)) var/mob/living/carbon/human/H = the_item var/obj/item/organ/external/limb = H.get_organ(user.zone_selected) @@ -412,15 +415,14 @@ revert_cast() return FALSE user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!") - var/oldloc = H.loc - if(!do_mob(user,H,EAT_MOB_DELAY)) + if(!do_mob(user, H, EAT_MOB_DELAY)) to_chat(user, "You were interrupted before you could eat [the_item]!") else if(!limb || !H) return - if(H.loc != oldloc) - to_chat(user, "\The [limb] moved away from your mouth!") - return + if(!user.Adjacent(the_item)) + to_chat(user, "You need to be next to [the_item] for this!") + return FALSE user.visible_message("[user] [pick("chomps","bites")] off [the_item]'s [limb]!") playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0) @@ -476,6 +478,7 @@ invocation_type = "none" action_icon_state = "genetic_jump" + var/leap_distance = 10 /datum/spell/leap/create_new_targeting() return new /datum/spell_targeting/self @@ -508,15 +511,25 @@ user.layer = 9 user.flying = TRUE - for(var/i=0, i<10, i++) + for(var/i in 1 to leap_distance) + var/turf/hit_turf = get_step(user, user.dir) + var/atom/hit_atom = get_blocking_atom(hit_turf) + if(hit_atom) + hit_atom.hit_by_thrown_mob(user, damage = 10) + break + step(user, user.dir) - if(i < 5) user.pixel_y += 8 - else user.pixel_y -= 8 + if(i < 6) + user.pixel_y += 8 + else + user.pixel_y -= 8 sleep(1) + user.flying = prevFlying + user.pixel_y = 0 // In case leap was varedited to be longer or shorter if(HAS_TRAIT(user, TRAIT_FAT) && prob(66)) - user.visible_message("[user.name] crashes due to [user.p_their()] heavy weight!") + user.visible_message("[user.name] crashes due to [user.p_their()] heavy weight!") //playsound(user.loc, 'zhit.wav', 50, 1) user.AdjustWeakened(20 SECONDS) user.AdjustStunned(10 SECONDS) @@ -539,6 +552,24 @@ container.pixel_x = 0 container.pixel_y = 0 +/datum/spell/leap/proc/get_blocking_atom(turf/turf_to_check) + if(!turf_to_check) + return FALSE + + if(turf_to_check.density) + return turf_to_check + + for(var/atom/movable/hit_thing in turf_to_check) + if(isliving(hit_thing)) + var/mob/living/hit_mob = hit_thing + return hit_mob.density + + if(isobj(hit_thing)) + var/obj/hit_obj = hit_thing + return hit_obj.density + + return FALSE + //////////////////////////////////////////////////////////////////////// // WAS: /datum/bioEffect/polymorphism diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e2a0d9a18a1..29dfb1fdd2f 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -438,14 +438,14 @@ /proc/get_nuke_code() var/nukecode = "ERROR" - for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines) + for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list) if(bomb && bomb.r_code && is_station_level(bomb.z)) nukecode = bomb.r_code return nukecode /proc/get_nuke_status() var/nuke_status = NUKE_MISSING - for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines) + for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list) if(is_station_level(bomb.z)) nuke_status = NUKE_CORE_MISSING if(bomb.core) diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 9d85e02c738..6e7eefce904 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -3,7 +3,62 @@ #define MIND_DEVICE_MESSAGE 1 #define MIND_DEVICE_CONTROL 2 -//AGENT VEST +#define BATON_STUN 0 +#define BATON_SLEEP 1 +#define BATON_CUFF 2 +#define BATON_PROBE 3 +#define BATON_MODES 4 + +/* +CONTENTS: +1. AGENT GEAR +2. SCIENTIST GEAR +3. ENGINEERING TOOLS +4. MEDICAL TOOLS +5. JANITORIAL TOOLS +6. STRUCTURES +*/ + +// Setting up abductor exclusivity. +/obj/item/abductor + name = "generic abductor item" + icon = 'icons/obj/abductor.dmi' + desc = "You are not supposed to be able to see this. If you can see this, please make an issue report on GitHub." + +/obj/item/abductor/proc/AbductorCheck(user) + if(isabductor(user)) + return TRUE + to_chat(user, "You can't figure how this works!") + return FALSE + +/obj/item/abductor/proc/ScientistCheck(user) + if(!AbductorCheck(user)) + return FALSE + + var/mob/living/carbon/human/H = user + var/datum/species/abductor/S = H.dna.species + if(S.scientist) + return TRUE + to_chat(user, "You're not trained to use this!") + return FALSE + +///////////////////////////////////////// +/////////////// AGENT GEAR ////////////// +///////////////////////////////////////// +/obj/item/clothing/head/helmet/abductor + name = "agent headgear" + desc = "Abduct with style - spiky style. Prevents digital tracking." + icon_state = "alienhelmet" + item_state = "alienhelmet" + blockTracking = 1 + origin_tech = "materials=7;magnets=4;abductor=3" + flags = BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + + sprite_sheets = list( + "Vox" = 'icons/mob/clothing/species/vox/head.dmi' + ) + /obj/item/clothing/suit/armor/abductor/vest name = "agent vest" desc = "A vest outfitted with advanced stealth technology. It has two modes - combat and stealth." @@ -129,113 +184,6 @@ break return ..() -/obj/item/abductor - icon = 'icons/obj/abductor.dmi' - -/obj/item/abductor/proc/AbductorCheck(user) - if(isabductor(user)) - return TRUE - to_chat(user, "You can't figure how this works!") - return FALSE - -/obj/item/abductor/proc/ScientistCheck(user) - if(!AbductorCheck(user)) - return FALSE - - var/mob/living/carbon/human/H = user - var/datum/species/abductor/S = H.dna.species - if(S.scientist) - return TRUE - to_chat(user, "You're not trained to use this!") - return FALSE - -/obj/item/abductor/gizmo - name = "science tool" - desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras." - icon_state = "gizmo_scan" - item_state = "gizmo" - origin_tech = "engineering=7;magnets=4;bluespace=4;abductor=3" - var/mode = GIZMO_SCAN - var/mob/living/marked = null - var/obj/machinery/abductor/console/console - -/obj/item/abductor/gizmo/attack_self(mob/user) - if(!ScientistCheck(user)) - return - if(!console) - to_chat(user, "The device is not linked to a console!") - return - - if(mode == GIZMO_SCAN) - mode = GIZMO_MARK - icon_state = "gizmo_mark" - else - mode = GIZMO_SCAN - icon_state = "gizmo_scan" - to_chat(user, "You switch the device to [mode==GIZMO_SCAN? "SCAN": "MARK"] MODE") - -/obj/item/abductor/gizmo/attack(mob/living/M, mob/user) - if(!ScientistCheck(user)) - return - if(!console) - to_chat(user, "The device is not linked to console!") - return - - switch(mode) - if(GIZMO_SCAN) - scan(M, user) - if(GIZMO_MARK) - mark(M, user) - - -/obj/item/abductor/gizmo/afterattack(atom/target, mob/living/user, flag, params) - if(flag) - return - if(!ScientistCheck(user)) - return - if(!console) - to_chat(user, "The device is not linked to console!") - return - - switch(mode) - if(GIZMO_SCAN) - scan(target, user) - if(GIZMO_MARK) - mark(target, user) - -/obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user) - if(ishuman(target)) - console.AddSnapshot(target) - to_chat(user, "You scan [target] and add [target.p_them()] to the database.") - -/obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user) - if(marked == target) - to_chat(user, "This specimen is already marked!") - return - if(ishuman(target)) - if(isabductor(target)) - marked = target - to_chat(user, "You mark [target] for future retrieval.") - else - prepare(target,user) - else - prepare(target,user) - -/obj/item/abductor/gizmo/proc/prepare(atom/target, mob/living/user) - if(get_dist(target,user)>1) - to_chat(user, "You need to be next to the specimen to prepare it for transport!") - return - to_chat(user, "You begin preparing [target] for transport...") - if(do_after(user, 100, target = target)) - marked = target - to_chat(user, "You finish preparing [target] for transport.") - -/obj/item/abductor/gizmo/Destroy() - if(console) - console.gizmo = null - return ..() - - /obj/item/abductor/silencer name = "abductor silencer" desc = "A compact device used to shut down communications equipment." @@ -277,75 +225,6 @@ R.listening = FALSE // Prevents the radio from buzzing due to the EMP, preserving possible stealthiness. R.emp_act(1) -/obj/item/abductor/mind_device - name = "mental interface device" - desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, or to send a command to a test subject with a charged gland." - icon_state = "mind_device_message" - item_state = "silencer" - var/mode = MIND_DEVICE_MESSAGE - -/obj/item/abductor/mind_device/attack_self(mob/user) - if(!ScientistCheck(user)) - return - - if(mode == MIND_DEVICE_MESSAGE) - mode = MIND_DEVICE_CONTROL - icon_state = "mind_device_control" - else - mode = MIND_DEVICE_MESSAGE - icon_state = "mind_device_message" - to_chat(user, "You switch the device to [mode == MIND_DEVICE_MESSAGE ? "TRANSMISSION" : "COMMAND"] MODE") - -/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params) - if(!ScientistCheck(user)) - return - - switch(mode) - if(MIND_DEVICE_CONTROL) - mind_control(target, user) - if(MIND_DEVICE_MESSAGE) - mind_message(target, user) - -/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user) - if(iscarbon(target)) - var/mob/living/carbon/C = target - var/obj/item/organ/internal/heart/gland/G = C.get_organ_slot("heart") - if(!istype(G)) - to_chat(user, "Your target does not have an experimental gland!") - return - if(!G.mind_control_uses) - to_chat(user, "Your target's gland is spent!") - return - if(G.active_mind_control) - to_chat(user, "Your target is already under a mind-controlling influence!") - return - - var/command = tgui_input_text(user, "Enter the command for your target to follow. Uses Left: [G.mind_control_uses], Duration: [DisplayTimeText(G.mind_control_duration)]", "Enter command") - if(!command) - return - if(QDELETED(user) || user.get_active_hand() != src || loc != user) - return - if(QDELETED(G)) - return - G.mind_control(command, user) - to_chat(user, "You send the command to your target.") - -/obj/item/abductor/mind_device/proc/mind_message(atom/target, mob/living/user) - if(isliving(target)) - var/mob/living/L = target - if(L.stat == DEAD) - to_chat(user, "Your target is dead!") - return - var/message = tgui_input_text(user, "Write a message to send to your target's brain.", "Enter message") - if(!message) - return - if(QDELETED(L) || L.stat == DEAD) - return - - to_chat(L, "You hear a voice in your head saying: [message]") - to_chat(user, "You send the message to your target.") - log_say("[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", user) - /obj/item/gun/energy/alien name = "alien pistol" desc = "A complicated gun that fires bursts of high-intensity radiation." @@ -357,41 +236,6 @@ trigger_guard = TRIGGER_GUARD_ALLOW_ALL can_holster = TRUE -/obj/item/paper/abductor - name = "Dissection Guide" - icon_state = "alienpaper_words" - info = {"Dissection for Dummies
-
- 1.Acquire fresh specimen.
- 2.Put the specimen on operating table.
- 3.Apply scalpel to the chest, preparing for experimental dissection.
- 4.Apply scalpel to specimen's torso.
- 5.Clamp bleeders on specimen's torso with a hemostat.
- 6.Retract skin of specimen's torso with a retractor.
- 7.Saw through the specimen's torso with a saw.
- 8.Apply retractor again to specimen's torso.
- 9.Search through the specimen's torso with your hands to remove any superfluous organs.
- 10.Insert replacement gland (Retrieve one from gland storage).
- 11.Cauterize the patient's torso with a cautery.
- 12.Consider dressing the specimen back to not disturb the habitat.
- 13.Put the specimen in the experiment machinery.
- 14.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.
- 15.You will receive one supply credit, and the subject will be counted towards your quota.
-
-Congratulations! You are now trained for invasive xenobiology research!"} - -/obj/item/paper/abductor/update_icon_state() - return - -/obj/item/paper/abductor/AltClick() - return - -#define BATON_STUN 0 -#define BATON_SLEEP 1 -#define BATON_CUFF 2 -#define BATON_PROBE 3 -#define BATON_MODES 4 - /obj/item/abductor_baton name = "advanced baton" desc = "A quad-mode baton used for incapacitation and restraining of specimens." @@ -590,6 +434,281 @@ Congratulations! You are now trained for invasive xenobiology research!"} /obj/item/radio/headset/abductor/screwdriver_act() return// Stops humans from disassembling abductor headsets. +///////////////////////////////////////// +///////////// SCIENTIST GEAR //////////// +///////////////////////////////////////// +/obj/item/abductor/gizmo + name = "science tool" + desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras." + icon_state = "gizmo_scan" + item_state = "gizmo" + origin_tech = "engineering=7;magnets=4;bluespace=4;abductor=3" + var/mode = GIZMO_SCAN + var/mob/living/marked = null + var/obj/machinery/abductor/console/console + +/obj/item/abductor/gizmo/attack_self(mob/user) + if(!ScientistCheck(user)) + return + if(!console) + to_chat(user, "The device is not linked to a console!") + return + + if(mode == GIZMO_SCAN) + mode = GIZMO_MARK + icon_state = "gizmo_mark" + else + mode = GIZMO_SCAN + icon_state = "gizmo_scan" + to_chat(user, "You switch the device to [mode==GIZMO_SCAN? "SCAN": "MARK"] MODE") + +/obj/item/abductor/gizmo/attack(mob/living/M, mob/user) + if(!ScientistCheck(user)) + return + if(!console) + to_chat(user, "The device is not linked to console!") + return + + switch(mode) + if(GIZMO_SCAN) + scan(M, user) + if(GIZMO_MARK) + mark(M, user) + +/obj/item/abductor/gizmo/afterattack(atom/target, mob/living/user, flag, params) + if(flag) + return + if(!ScientistCheck(user)) + return + if(!console) + to_chat(user, "The device is not linked to console!") + return + + switch(mode) + if(GIZMO_SCAN) + scan(target, user) + if(GIZMO_MARK) + mark(target, user) + +/obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user) + if(ishuman(target)) + console.AddSnapshot(target) + to_chat(user, "You scan [target] and add [target.p_them()] to the database.") + +/obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user) + if(marked == target) + to_chat(user, "This specimen is already marked!") + return + if(ishuman(target)) + if(isabductor(target)) + marked = target + to_chat(user, "You mark [target] for future retrieval.") + else + prepare(target,user) + else + prepare(target,user) + +/obj/item/abductor/gizmo/proc/prepare(atom/target, mob/living/user) + if(get_dist(target,user)>1) + to_chat(user, "You need to be next to the specimen to prepare it for transport!") + return + to_chat(user, "You begin preparing [target] for transport...") + if(do_after(user, 100, target = target)) + marked = target + to_chat(user, "You finish preparing [target] for transport.") + +/obj/item/abductor/gizmo/Destroy() + if(console) + console.gizmo = null + return ..() + +/obj/item/abductor/mind_device + name = "mental interface device" + desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, or to send a command to a test subject with a charged gland." + icon_state = "mind_device_message" + item_state = "silencer" + var/mode = MIND_DEVICE_MESSAGE + +/obj/item/abductor/mind_device/attack_self(mob/user) + if(!ScientistCheck(user)) + return + + if(mode == MIND_DEVICE_MESSAGE) + mode = MIND_DEVICE_CONTROL + icon_state = "mind_device_control" + else + mode = MIND_DEVICE_MESSAGE + icon_state = "mind_device_message" + to_chat(user, "You switch the device to [mode == MIND_DEVICE_MESSAGE ? "TRANSMISSION" : "COMMAND"] MODE") + +/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params) + if(!ScientistCheck(user)) + return + + switch(mode) + if(MIND_DEVICE_CONTROL) + mind_control(target, user) + if(MIND_DEVICE_MESSAGE) + mind_message(target, user) + +/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user) + if(iscarbon(target)) + var/mob/living/carbon/C = target + var/obj/item/organ/internal/heart/gland/G = C.get_organ_slot("heart") + if(!istype(G)) + to_chat(user, "Your target does not have an experimental gland!") + return + if(!G.mind_control_uses) + to_chat(user, "Your target's gland is spent!") + return + if(G.active_mind_control) + to_chat(user, "Your target is already under a mind-controlling influence!") + return + + var/command = tgui_input_text(user, "Enter the command for your target to follow. Uses Left: [G.mind_control_uses], Duration: [DisplayTimeText(G.mind_control_duration)]", "Enter command") + if(!command) + return + if(QDELETED(user) || user.get_active_hand() != src || loc != user) + return + if(QDELETED(G)) + return + G.mind_control(command, user) + to_chat(user, "You send the command to your target.") + +/obj/item/abductor/mind_device/proc/mind_message(atom/target, mob/living/user) + if(isliving(target)) + var/mob/living/L = target + if(L.stat == DEAD) + to_chat(user, "Your target is dead!") + return + var/message = tgui_input_text(user, "Write a message to send to your target's brain.", "Enter message") + if(!message) + return + if(QDELETED(L) || L.stat == DEAD) + return + + to_chat(L, "You hear a voice in your head saying: [message]") + to_chat(user, "You send the message to your target.") + log_say("[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", user) + +/obj/item/paper/abductor + name = "Dissection Guide" + icon_state = "alienpaper_words" + info = {"Dissection for Dummies
+
+ 1.Acquire fresh specimen.
+ 2.Put the specimen on operating table.
+ 3.Apply scalpel to the chest, preparing for experimental dissection.
+ 4.Apply scalpel to specimen's torso.
+ 5.Clamp bleeders on specimen's torso with a hemostat.
+ 6.Retract skin of specimen's torso with a retractor.
+ 7.Saw through the specimen's torso with a saw.
+ 8.Apply retractor again to specimen's torso.
+ 9.Search through the specimen's torso with your hands to remove any superfluous organs.
+ 10.Insert replacement gland (Retrieve one from gland storage).
+ 11.Cauterize the patient's torso with a cautery.
+ 12.Consider dressing the specimen back to not disturb the habitat.
+ 13.Put the specimen in the experiment machinery.
+ 14.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.
+ 15.You will receive one supply credit, and the subject will be counted towards your quota.
+
+Congratulations! You are now trained for invasive xenobiology research!"} + +/obj/item/paper/abductor/update_icon_state() + return + +/obj/item/paper/abductor/AltClick() + return + +///////////////////////////////////////// +/////////// ENGINEERING TOOLS /////////// +///////////////////////////////////////// +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + w_class = WEIGHT_CLASS_SMALL + light_intensity = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + requires_fuel = FALSE + refills_over_time = TRUE + low_fuel_changes_icon = FALSE + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + icon_state = "crowbar" + usesound = 'sound/weapons/sonic_jackhammer.ogg' + toolspeed = 0.1 + w_class = WEIGHT_CLASS_SMALL + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + random_color = FALSE + +/obj/item/wirecutters/abductor/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) + +/obj/item/multitool/abductor + name = "alien multitool" + desc = "An omni-technological interface." + icon = 'icons/obj/abductor.dmi' + icon_state = "multitool" + toolspeed = 0.1 + w_class = WEIGHT_CLASS_SMALL + origin_tech = "magnets=5;engineering=5;abductor=3" + +/obj/item/multitool/abductor/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) + +/obj/item/storage/belt/military/abductor + name = "agent belt" + desc = "A belt used by abductor agents." + icon = 'icons/obj/abductor.dmi' + icon_state = "belt" + item_state = "security" + +/obj/item/storage/belt/military/abductor/full/populate_contents() + new /obj/item/screwdriver/abductor(src) + new /obj/item/wrench/abductor(src) + new /obj/item/weldingtool/abductor(src) + new /obj/item/crowbar/abductor(src) + new /obj/item/wirecutters/abductor(src) + new /obj/item/multitool/abductor(src) + new /obj/item/stack/cable_coil(src, 30, COLOR_WHITE) + +///////////////////////////////////////// +/////////// MEDICAL TOOLS /////////////// +///////////////////////////////////////// /obj/item/scalpel/alien name = "alien scalpel" desc = "It's a gleaming sharp knife made out of silvery-green metal." @@ -641,7 +760,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} /obj/item/FixOVein/alien name = "alien FixOVein" - desc = "Bloodless aliens would totally know how to stop internal bleeding...right?" + desc = "Bloodless aliens would totally know how to stop internal bleeding... Right?" icon = 'icons/obj/abductor.dmi' origin_tech = "materials=2;biotech=2;abductor=2" toolspeed = 0.25 @@ -653,21 +772,89 @@ Congratulations! You are now trained for invasive xenobiology research!"} origin_tech = "materials=2;biotech=2;abductor=2" toolspeed = 0.25 -/obj/item/clothing/head/helmet/abductor - name = "agent headgear" - desc = "Abduct with style - spiky style. Prevents digital tracking." - icon_state = "alienhelmet" - item_state = "alienhelmet" - blockTracking = 1 - origin_tech = "materials=7;magnets=4;abductor=3" - flags = BLOCKHAIR - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE +///////////////////////////////////////// +//////////// JANITORIAL TOOLS /////////// +///////////////////////////////////////// +/obj/item/mop/advanced/abductor + name = "alien mop" + desc = "A collapsible mop clearly used by aliens to clean up any evidence of a close encounter. The head produces a constant supply of water when run over a surface, seemingly out of nowhere." + icon = 'icons/obj/abductor.dmi' + icon_state = "mop_abductor" + mopcap = 100 + origin_tech = "materials=3;engineering=3;abductor=3" + refill_rate = 50 + refill_reagent = "water" + mopspeed = 10 - sprite_sheets = list( - "Vox" = 'icons/mob/clothing/species/vox/head.dmi' +/obj/item/soap/syndie/abductor + name = "alien soap" + desc = "Even bloodless aliens need to wash the grime off. Smells like gunpowder." + icon = 'icons/obj/abductor.dmi' + icon_state = "soap_abductor" + +/obj/item/lightreplacer/bluespace/abductor + name = "alien light replacer" + desc = "It's important to keep all the mysterious lights on a UFO functional when flying over backwater country." + icon = 'icons/obj/abductor.dmi' + icon_state = "lightreplacer_abductor" + origin_tech = "magnets=3;engineering=4;abductor=3" + max_uses = 40 + uses = 20 + +/obj/item/melee/flyswatter/abductor + name = "alien flyswatter" + desc = "For killing alien insects, obviously." + icon = 'icons/obj/abductor.dmi' + icon_state = "flyswatter_abductor" + item_state = "flyswatter_abductor" + origin_tech = "abductor=1" + force = 2 // Twice as powerful thanks to alien technology! + throwforce = 2 + +/obj/item/reagent_containers/spray/cleaner/safety/abductor // Essentially an Advanced Space Cleaner, but abductor-themed. For the implant. + name = "alien space cleaner" + desc = "An alien spray bottle contaning alien-brand non-foaming space cleaner! It only accepts space cleaner." + icon = 'icons/obj/abductor.dmi' + icon_state = "cleaner_abductor" + item_state = "cleaner_abductor" + volume = 500 + spray_maxrange = 3 + spray_currentrange = 3 + list_reagents = list("cleaner" = 500) + +/obj/item/storage/belt/janitor/abductor + name = "alien janibelt" + desc = "A belt used to hold out-of-this-world cleaning supplies! Used by abductors to keep their ships clean." + icon = 'icons/obj/abductor.dmi' + icon_state = "janibelt_abductor" + item_state = "security" + storage_slots = 7 + can_hold = list( + /obj/item/grenade/chem_grenade/cleaner, + /obj/item/lightreplacer, + /obj/item/flashlight, + /obj/item/reagent_containers/spray, + /obj/item/soap, + /obj/item/holosign_creator/janitor, + /obj/item/melee/flyswatter, + /obj/item/storage/bag/trash, + /obj/item/push_broom, + /obj/item/door_remote/janikeyring, + /obj/item/mop/advanced/abductor ) -// Operating Table / Beds / Lockers +/obj/item/storage/belt/janitor/abductor/full/populate_contents() + new /obj/item/mop/advanced/abductor(src) + new /obj/item/soap/syndie/abductor(src) + new /obj/item/lightreplacer/bluespace/abductor(src) + new /obj/item/storage/bag/trash/bluespace(src) + new /obj/item/melee/flyswatter/abductor(src) + new /obj/item/reagent_containers/spray/cleaner/safety/abductor(src) + new /obj/item/holosign_creator/janitor(src) + +///////////////////////////////////////// +/////////////// STRUCTURES ////////////// +///////////////////////////////////////// /obj/structure/bed/abductor name = "resting contraption" desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" diff --git a/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm b/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm index 15cf5eeacde..82a903afa37 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_outfits.dm @@ -50,7 +50,6 @@ /datum/outfit/abductor/scientist name = "Abductor Scientist" - backpack_contents = list( /obj/item/abductor/gizmo = 1 ) diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm index 01694f122ce..9ce27a93ab3 100644 --- a/code/game/gamemodes/nuclear/nuclear_challenge.dm +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -84,7 +84,7 @@ if(declaring_war) to_chat(user, "You are already in the process of declaring war! Make your mind up.") return FALSE - if(length(GLOB.player_list) < CHALLENGE_MIN_PLAYERS) + if(length(get_living_players(exclude_nonhuman = FALSE, exclude_offstation = TRUE)) < CHALLENGE_MIN_PLAYERS) to_chat(user, "The enemy crew is too small to be worth declaring war on.") return FALSE if(!is_admin_level(user.z)) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 8d4b34139fa..921040d015d 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -15,7 +15,7 @@ GLOBAL_VAR(bomb_set) name = "\improper Nuclear Fission Explosive" desc = "Uh oh. RUN!!!!" icon = 'icons/obj/nuclearbomb.dmi' - icon_state = "nuclearbomb0" + icon_state = "nuclearbomb1" density = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF flags_2 = NO_MALF_EFFECT_2 | CRITICAL_ATOM_2 @@ -25,8 +25,6 @@ GLOBAL_VAR(bomb_set) /// Are our bolts *supposed* to be in the floor, may not actually cause anchoring if the bolts are cut var/extended = TRUE - /// If true, prevents the lights on the nuke - var/lighthack = FALSE /// Countdown to boom var/timeleft = 120 /// Are we counting down? @@ -55,6 +53,10 @@ GLOBAL_VAR(bomb_set) var/core_stage = NUKE_CORE_EVERYTHING_FINE ///How many sheets of various metals we need to fix it var/sheets_to_fix = 5 + /// Is this a training bomb? + var/training = FALSE + /// Prefix to add, if any, on icon states for this bomb + var/sprite_prefix = "" ///Bombs Internal Radio var/obj/item/radio/radio @@ -70,9 +72,10 @@ GLOBAL_VAR(bomb_set) . = ..() r_code = rand(10000, 99999) // Creates a random code upon object spawn. wires = new/datum/wires/nuclearbomb(src) - ADD_TRAIT(src, TRAIT_OBSCURED_WIRES, ROUNDSTART_TRAIT) previous_level = SSsecurity_level.get_current_level_as_text() - GLOB.poi_list |= src + if(!training) + GLOB.poi_list |= src + GLOB.nuke_list |= src core = new /obj/item/nuke_core/plutonium(src) STOP_PROCESSING(SSobj, core) //Let us not irradiate the vault by default. update_icon(UPDATE_OVERLAYS) @@ -81,14 +84,26 @@ GLOBAL_VAR(bomb_set) radio.follow_target = src radio.config(list("Special Ops" = 0)) +/obj/machinery/nuclearbomb/syndicate/Initialize() + . = ..() + wires.labelled = FALSE + ADD_TRAIT(src, TRAIT_OBSCURED_WIRES, ROUNDSTART_TRAIT) + GLOB.syndi_nuke_list |= src + /obj/machinery/nuclearbomb/Destroy() SStgui.close_uis(wires) QDEL_NULL(wires) QDEL_NULL(core) QDEL_NULL(radio) - GLOB.poi_list.Remove(src) + if(!training) + GLOB.poi_list.Remove(src) + GLOB.nuke_list.Remove(src) return ..() +/obj/machinery/nuclearbomb/syndicate/Destroy() + GLOB.syndi_nuke_list.Remove(src) + . = ..() + /obj/machinery/nuclearbomb/process() if(timing) GLOB.bomb_set = TRUE // So long as there is one nuke timing, it means one nuke is armed. @@ -99,6 +114,8 @@ GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb/examine(mob/user) . = ..() + if(training) + . += "Alt-Click to reset the bomb." if(!panel_open) . += "The outer panel is screwed shut." switch(removal_stage) @@ -126,15 +143,15 @@ GLOBAL_VAR(bomb_set) underlays.Cut() set_light(0) - if(!lighthack) - underlays += emissive_appearance(icon, "nuclearbomb_lightmask") + if(!wires.is_cut(WIRE_NUKE_LIGHT)) + underlays += emissive_appearance(icon, sprite_prefix + "nukelights_lightmask") set_light(1, LIGHTING_MINIMUM_POWER) if(panel_open) - . += "hackpanel_open" + . += sprite_prefix + "hackpanel_open" if(anchored) // Using anchored due to removal_stage deanchoring having multiple steps - . += "nukebolts" + . += sprite_prefix + "nukebolts" // Selected stage lets us show the open core, even if the front panel is closed var/selected_stage = removal_stage @@ -151,6 +168,12 @@ GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb/attackby(obj/item/O as obj, mob/user as mob, params) if(istype(O, /obj/item/disk/nuclear)) if(extended) + if(auth) + to_chat(user, "There's already a disk in the slot!") + return + if((istype(O, /obj/item/disk/nuclear/training) && !training) || (training && !istype(O, /obj/item/disk/nuclear/training))) + to_chat(user, "[O] doesn't fit into [src]!") + return if(!user.drop_item()) to_chat(user, "[O] is stuck to your hand!") return @@ -212,12 +235,15 @@ GLOBAL_VAR(bomb_set) if(!I.tool_use_check(user, 0)) return if(removal_stage == NUKE_COVER_OFF) - user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [I]...") + user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [I]...") if(!I.use_tool(src, user, 15, volume = I.tool_volume) || removal_stage != NUKE_COVER_OFF) return - user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") + user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") removal_stage = NUKE_COVER_OPEN if(removal_stage == NUKE_CORE_EVERYTHING_FINE) + if(training) + to_chat(user, "This is where you'd take off the plate to access the internal core, but this training bomb doesn't have one.") + return user.visible_message("[user] starts removing [src]'s outer core plate...", "You start removing [src]'s outer core plate...") if(!I.use_tool(src, user, 4 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_EVERYTHING_FINE) return @@ -235,10 +261,10 @@ GLOBAL_VAR(bomb_set) if(core) START_PROCESSING(SSobj, core) if(removal_stage == NUKE_UNWRENCHED) - user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") + user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED) return - user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") + user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") anchored = FALSE removal_stage = NUKE_MOBILE update_icon(UPDATE_OVERLAYS) @@ -251,10 +277,10 @@ GLOBAL_VAR(bomb_set) . = TRUE if(!I.tool_use_check(user, 0)) return - user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") + user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") if(!I.use_tool(src, user, 50, volume = I.tool_volume) || removal_stage != NUKE_SEALANT_OPEN) return - user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") + user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") removal_stage = NUKE_UNWRENCHED update_icon(UPDATE_OVERLAYS) @@ -273,23 +299,23 @@ GLOBAL_VAR(bomb_set) if(auth || (istype(I, /obj/item/screwdriver/nuke) && !is_syndicate)) if(!panel_open) panel_open = TRUE - to_chat(user, "You unscrew the control panel of [src].") + to_chat(user, "You unscrew the control panel of [src].") anchor_stage = removal_stage removal_stage = core_stage else panel_open = FALSE - to_chat(user, "You screw the control panel of [src] back on.") + to_chat(user, "You screw the control panel of [src] back on.") core_stage = removal_stage removal_stage = anchor_stage else if(!panel_open) - to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.") + to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.") if(panel_open) panel_open = FALSE - to_chat(user, "You screw the control panel of [src] back on.") + to_chat(user, "You screw the control panel of [src] back on.") core_stage = removal_stage removal_stage = anchor_stage - flick("nuclearbombc", src) + flick(sprite_prefix + "nuclearbombc", src) update_icon(UPDATE_OVERLAYS) /obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I) @@ -397,6 +423,8 @@ GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb/proc/is_auth(mob/user) if(auth) + if(istype(auth, /obj/item/disk/nuclear/training) && !training) + return FALSE return TRUE else if(user.can_admin_interact()) return TRUE @@ -409,6 +437,9 @@ GLOBAL_VAR(bomb_set) . = TRUE if(exploded) return + if(wires.is_cut(WIRE_NUKE_CONTROL)) + to_chat(usr, "The control panel isn't responding! Something must be wrong with its wiring!") + return FALSE switch(action) if("deploy") if(removal_stage != NUKE_MOBILE) @@ -416,9 +447,9 @@ GLOBAL_VAR(bomb_set) visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring!") else visible_message("[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - if(!lighthack) - flick("nuclearbombc", src) - icon_state = "nuclearbomb1" + if(!wires.is_cut(WIRE_NUKE_LIGHT)) + flick(sprite_prefix + "nuclearbombc", src) + icon_state = sprite_prefix + "nuclearbomb1" update_icon(UPDATE_OVERLAYS) extended = TRUE return @@ -433,6 +464,8 @@ GLOBAL_VAR(bomb_set) else var/obj/item/I = usr.get_active_hand() if(istype(I, /obj/item/disk/nuclear)) + if((istype(I, /obj/item/disk/nuclear/training) && !training) || (training && !istype(I, /obj/item/disk/nuclear/training))) + return usr.drop_item() I.forceMove(src) auth = I @@ -491,43 +524,57 @@ GLOBAL_VAR(bomb_set) return timeleft = time if("toggle_safety") + if(wires.is_cut(WIRE_NUKE_SAFETY)) + to_chat(usr, "The safety isn't responding! Something must be wrong with its wiring!") + return FALSE safety = !(safety) if(safety) - if(!is_syndicate) + if(!is_syndicate && !training) SSsecurity_level.set_level(previous_level) timing = FALSE - GLOB.bomb_set = FALSE + if(!training) + GLOB.bomb_set = FALSE if("toggle_armed") if(safety) to_chat(usr, "The safety is still on.") return - if(!core) + if(!core && !training) to_chat(usr, "[src]'s screen blinks red! There is no plutonium core in [src]!") return - timing = !(timing) - if(timing) - if(!lighthack) - icon_state = "nuclearbomb2" + if(!timing) + if(wires.is_cut(WIRE_NUKE_DETONATOR)) + to_chat(usr, "[src] isn't arming! Something must be wrong with its wiring!") + return FALSE + timing = TRUE + if(!wires.is_cut(WIRE_NUKE_LIGHT)) + icon_state = sprite_prefix + "nuclearbomb2" update_icon(UPDATE_OVERLAYS) - if(!safety) + if(!safety && !training) message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]") if(!is_syndicate && SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_EPSILON) SSsecurity_level.set_level(SEC_LEVEL_DELTA) GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke if(SSsecurity_level.get_current_level_as_number() == SEC_LEVEL_EPSILON) radio.autosay("The Nuclear Bomb has been armed, retreat from the station immediately!", name, "Special Ops") - else + else if(!training) GLOB.bomb_set = TRUE else - if(!is_syndicate) + if(wires.is_cut(WIRE_NUKE_DISARM)) + to_chat(usr, "[src] isn't disarming! Something must be wrong with its wiring!") + return FALSE + timing = FALSE + if(!is_syndicate && !training) SSsecurity_level.set_level(previous_level) - GLOB.bomb_set = FALSE - if(!lighthack) - icon_state = "nuclearbomb1" + if(!training) + GLOB.bomb_set = FALSE + if(!wires.is_cut(WIRE_NUKE_LIGHT)) + icon_state = sprite_prefix + "nuclearbomb1" update_icon(UPDATE_OVERLAYS) - /obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B) + if(training) + qdel(src) + return if(exploded) return if(timing) //boom @@ -567,16 +614,19 @@ GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb/proc/explode() + if(training) + atom_say("You've triggered the detonate wire. You are dead.") + return if(safety) timing = FALSE return exploded = TRUE yes_code = FALSE safety = TRUE - if(!lighthack) - icon_state = "nuclearbomb3" + if(!wires.is_cut(WIRE_NUKE_LIGHT)) + icon_state = sprite_prefix + "nuclearbomb3" update_icon(UPDATE_OVERLAYS) - playsound(src,'sound/machines/alarm.ogg',100,0,5) + playsound(src, 'sound/machines/alarm.ogg', 100, FALSE, 5) if(SSticker && SSticker.mode) SSticker.mode.explosion_in_progress = TRUE SSticker.event_blackbox(outcome = ROUND_END_NUCLEAR) @@ -618,23 +668,6 @@ GLOBAL_VAR(bomb_set) return return -/obj/machinery/nuclearbomb/proc/reset_lighthack_callback() - lighthack = !lighthack - -/obj/machinery/nuclearbomb/proc/reset_safety_callback() - safety = !safety - if(safety == 1) - if(!is_syndicate) - SSsecurity_level.set_level(previous_level) - visible_message("[src] quiets down.") - if(!lighthack) - if(icon_state == "nuclearbomb2") - icon_state = "nuclearbomb1" - update_icon(UPDATE_OVERLAYS) - - else - visible_message("[src] emits a quiet whirling noise!") - //==========DAT FUKKEN DISK=============== /obj/item/disk/nuclear name = "nuclear authentication disk" @@ -645,6 +678,8 @@ GLOBAL_VAR(bomb_set) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF /// Is the disk restricted to the station? If true, also respawns the disk when deleted var/restricted_to_station = TRUE + /// Is this a training disk? + var/training = FALSE /obj/item/disk/nuclear/unrestricted name = "unrestricted nuclear authentication disk" @@ -655,7 +690,9 @@ GLOBAL_VAR(bomb_set) ..() if(restricted_to_station) START_PROCESSING(SSobj, src) - GLOB.poi_list |= src + if(!training) + GLOB.poi_list |= src + GLOB.nad_list |= src /obj/item/disk/nuclear/process() if(!restricted_to_station) @@ -682,26 +719,32 @@ GLOBAL_VAR(bomb_set) /obj/item/disk/nuclear/Destroy(force) var/turf/diskturf = get_turf(src) + if(training) + return ..() + if(force) - message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - JMP":"nonexistent location"]).") + message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - JMP":"nonexistent location"]).") log_game("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]).") GLOB.poi_list.Remove(src) + GLOB.nad_list.Remove(src) STOP_PROCESSING(SSobj, src) return ..() if(!restricted_to_station) // Non-restricted NADs should be allowed to be deleted, otherwise it becomes a restricted NAD when teleported - message_admins("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - JMP":"nonexistent location"]). It will not respawn.") + message_admins("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - JMP":"nonexistent location"]). It will not respawn.") log_game("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]). It will not respawn.") GLOB.poi_list.Remove(src) + GLOB.nad_list.Remove(src) STOP_PROCESSING(SSobj, src) return ..() var/turf/new_spawn = find_respawn() if(new_spawn) GLOB.poi_list.Remove(src) + GLOB.nad_list.Remove(src) var/obj/item/disk/nuclear/NEWDISK = new(new_spawn) transfer_fingerprints_to(NEWDISK) - message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).") + message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).") log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y], [diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).") ..() return QDEL_HINT_HARDDEL_NOW // We want this to be deleted ASAP, but we want refs properly cleared too @@ -720,6 +763,54 @@ GLOBAL_VAR(bomb_set) if(length(open_turfs)) return pick(open_turfs) +/// MARK: TRAINING NUKE + +/obj/machinery/nuclearbomb/training + name = "training nuclear bomb" + desc = "A fake nuke used to practice nuclear device operations. \ + The '1' key on the keypad appears to be significantly more worn than the other keys." + icon_state = "t_nuclearbomb1" + resistance_flags = null + training = TRUE + sprite_prefix = "t_" + +/obj/machinery/nuclearbomb/training/Initialize() + . = ..() + r_code = 11111 //Uuh.. one! + qdel(core) + +/obj/machinery/nuclearbomb/training/process() + if(timing) + timeleft = max(timeleft - 2, 0) // 2 seconds per process() + if(timeleft <= 0) + INVOKE_ASYNC(src, PROC_REF(training_detonation)) + +/obj/machinery/nuclearbomb/training/blob_act(obj/structure/blob/B) + qdel(src) + +/obj/machinery/nuclearbomb/training/AltClick(mob/user) + . = ..() + to_chat(user, "You hit the reset button on [src].") + training_reset() + +/obj/machinery/nuclearbomb/training/proc/training_detonation() + atom_say("Nuclear device detonated. Resetting...") + training_reset() + +/obj/machinery/nuclearbomb/training/proc/training_reset() + if(auth) + auth.forceMove(get_turf(src)) + new /obj/machinery/nuclearbomb/training(get_turf(src)) + qdel(src) + +/obj/item/disk/nuclear/training + name = "training authentication disk" + desc = "The code is 11111." + icon_state = "trainingdisk" + resistance_flags = null + restricted_to_station = FALSE + training = TRUE + #undef NUKE_INTACT #undef NUKE_COVER_OFF #undef NUKE_COVER_OPEN diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index c988d1709eb..f5f8487e1b2 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -96,15 +96,15 @@ /obj/item/pinpointer/proc/scandisk() if(!the_disk) - the_disk = locate() in GLOB.poi_list + the_disk = locate() in GLOB.nad_list /obj/item/pinpointer/proc/scanbomb() if(!syndicate) if(!the_bomb) - the_bomb = locate() in GLOB.poi_list + the_bomb = locate() in GLOB.nuke_list else if(!the_s_bomb) - the_s_bomb = locate() in GLOB.poi_list + the_s_bomb = locate() in GLOB.syndi_nuke_list /obj/item/pinpointer/proc/point_at_target(atom/target) if(!target) diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index ca40f18d0bc..daf72168235 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -106,6 +106,11 @@ protected_jobs = list("Captain") location_override = "the Captain's Office" +/datum/theft_objective/nukedisc/check_special_completion(obj/item/I) + if(istype(I, /obj/item/disk/nuclear/training)) //Haha no + return FALSE + return TRUE + /datum/theft_objective/reactive name = "any type of reactive armor" typepath = /obj/item/clothing/suit/armor/reactive diff --git a/code/game/gamemodes/wizard/magic_tarot.dm b/code/game/gamemodes/wizard/magic_tarot.dm index e3efcfa8128..5d4cdd5603f 100644 --- a/code/game/gamemodes/wizard/magic_tarot.dm +++ b/code/game/gamemodes/wizard/magic_tarot.dm @@ -389,11 +389,9 @@ card_icon = "wheel_of_fortune" /datum/tarot/wheel_of_fortune/activate(mob/living/target) - var/list/static/bad_vendors = list( - /obj/machinery/economy/vending/liberationstation, - /obj/machinery/economy/vending/toyliberationstation, - /obj/machinery/economy/vending/wallmed - ) + var/list/static/bad_vendors = typesof(/obj/machinery/economy/vending/liberationstation)\ + + typesof(/obj/machinery/economy/vending/toyliberationstation)\ + + typesof(/obj/machinery/economy/vending/wallmed) // Future proofing in case we add more subtypes of disallowed vendors var/turf/target_turf = get_turf(target) var/vendorpath = pick(subtypesof(/obj/machinery/economy/vending) - bad_vendors) new vendorpath(target_turf) diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm index 7800f4b68a7..0f49925b52f 100644 --- a/code/game/jobs/job/central.dm +++ b/code/game/jobs/job/central.dm @@ -41,10 +41,8 @@ /obj/item/organ/internal/cyberimp/arm/combat/centcom ) -/datum/outfit/job/ntnavyofficer/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) +/datum/outfit/job/ntnavyofficer/on_mind_initialize(mob/living/carbon/human/H) . = ..() - if(visualsOnly) - return H.mind.offstation_role = TRUE // CC Officials who lead ERTs, Death Squads, etc. @@ -97,10 +95,8 @@ /obj/item/organ/internal/cyberimp/arm/combat/centcom ) -/datum/outfit/job/ntspecops/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) +/datum/outfit/job/ntspecops/on_mind_initialize(mob/living/carbon/human/H) . = ..() - if(visualsOnly) - return H.mind.offstation_role = TRUE /datum/job/ntspecops/solgovspecops @@ -121,4 +117,7 @@ if(istype(I)) apply_to_card(I, H, get_centcom_access(name), name, "lifetimeid") H.sec_hud_set_ID() + +/datum/outfit/job/ntspecops/solgovspecops/on_mind_initialize(mob/living/carbon/human/H) + . = ..() H.mind.offstation_role = TRUE diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 925e8e6f464..7ad8749098b 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -216,6 +216,7 @@ gear_leftovers += G /datum/outfit/job/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + . = ..() if(visualsOnly) return @@ -280,3 +281,16 @@ PDA.ownjob = C.assignment PDA.ownrank = C.rank PDA.name = "PDA-[H.real_name] ([PDA.ownjob])" + +/datum/outfit/job/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + var/obj/item/card/id/id = H.wear_id + if(!id) + return + var/datum/job/J = SSjobs.GetJobType(jobtype) + if(!J) + J = SSjobs.GetJob(H.job) + id.assignment = H.mind.role_alt_title ? H.mind.role_alt_title : J.title + if(!H.mind.initial_account) + return + id.associated_account_number = H.mind.initial_account.account_number diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 820b12c9a10..c8678be4e11 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -202,6 +202,9 @@ singlemutcheck(H, GLOB.soberblock, MUTCHK_FORCED) H.dna.default_blocks.Add(GLOB.soberblock) H.check_mutations = 1 + +/datum/outfit/job/bartender/on_mind_initialize(mob/living/carbon/human/H) + . = ..() ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT) ADD_TRAIT(H.mind, TRAIT_SLEIGHT_OF_HAND, ROUNDSTART_TRAIT) @@ -236,12 +239,10 @@ /obj/item/paper/chef=1,\ /obj/item/book/manual/wiki/chef_recipes=1) -/datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) - ..() - if(visualsOnly) - return +/datum/outfit/job/chef/on_mind_initialize(mob/living/carbon/human/H) + . = ..() var/datum/martial_art/cqc/under_siege/justacook = new - justacook.teach(H) + justacook.teach(H) // requires mind ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT) @@ -419,12 +420,14 @@ if(visualsOnly) return - if(H.mind) - H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null)) - H.mind.AddSpell(new /datum/spell/mime/speak(null)) - H.mind.miming = 1 qdel(H.GetComponent(/datum/component/footstep)) +/datum/outfit/job/mime/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null)) + H.mind.AddSpell(new /datum/spell/mime/speak(null)) + H.mind.miming = TRUE + /datum/job/janitor title = "Janitor" flag = JOB_JANITOR @@ -488,7 +491,7 @@ /datum/outfit/job/librarian/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() - if(!H.mind) + if(visualsOnly) return for(var/la in GLOB.all_languages) var/datum/language/new_language = GLOB.all_languages[la] diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm index f97ccfb5422..e0193a6c9be 100644 --- a/code/game/jobs/job/support_chaplain.dm +++ b/code/game/jobs/job/support_chaplain.dm @@ -32,11 +32,12 @@ if(visualsOnly) return - if(istype(H.mind)) - ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT) - INVOKE_ASYNC(src, PROC_REF(religion_pick), H) +/datum/outfit/job/chaplain/on_mind_initialize(mob/living/carbon/human/H) + . = ..() + ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT) + /datum/outfit/job/chaplain/proc/religion_pick(mob/living/carbon/human/user) var/obj/item/storage/bible/B = new /obj/item/storage/bible(get_turf(user)) B.customisable = TRUE // Only the initial bible is customisable diff --git a/code/game/jobs/job/syndicate_jobs.dm b/code/game/jobs/job/syndicate_jobs.dm index 089a5b26e4b..68a462ccc48 100644 --- a/code/game/jobs/job/syndicate_jobs.dm +++ b/code/game/jobs/job/syndicate_jobs.dm @@ -55,8 +55,11 @@ U.implant(H) U.hidden_uplink.uses = 2500 H.faction += "syndicate" + +/datum/outfit/job/syndicateofficer/on_mind_initialize(mob/living/carbon/human/H) + . = ..() var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.join_hud(H.mind.current) H.mind.offstation_role = TRUE set_antag_hud(H.mind.current, "hudoperative") - H.regenerate_icons() + INVOKE_ASYNC(H, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 4b254125135..36a0a848a2f 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -300,20 +300,7 @@ emagged = FALSE setMenuState(ui.user, COMM_SCREEN_MAIN) - if("RestartNanoMob") - if(SSmob_hunt) - if(SSmob_hunt.manual_reboot()) - var/loading_msg = pick("Respawning spawns", "Reticulating splines", "Flipping hat", - "Capturing all of them", "Fixing minor text issues", "Being the very best", - "Nerfing this", "Not communicating with playerbase", "Coding a ripoff in a 2D spaceman game") - to_chat(ui.user, "Restarting Nano-Mob Hunter GO! game server. [loading_msg]...") - else - to_chat(ui.user, "Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.") - else - to_chat(ui.user, "Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.") - // ADMIN CENTCOMM ONLY STUFF - if("send_to_cc_announcement_page") if(!ADMIN_CHECK(ui.user)) return diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 70a8a6e387f..0b34829a439 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -301,8 +301,9 @@ if(occupant_typecache) occupant_typecache = typecacheof(occupant_typecache) -/obj/machinery/suit_storage_unit/Destroy() - dump_contents() +/obj/machinery/suit_storage_unit/Destroy(force) + if(!force) + dump_contents() SStgui.close_uis(wires) QDEL_NULL(wires) return ..() diff --git a/code/game/machinery/vendors/generic_vendors.dm b/code/game/machinery/vendors/generic_vendors.dm index a25e252705f..d817a93c1fa 100644 --- a/code/game/machinery/vendors/generic_vendors.dm +++ b/code/game/machinery/vendors/generic_vendors.dm @@ -1301,7 +1301,6 @@ icon_panel = "wide_vendor" category = VENDOR_TYPE_SUPPLIES products = list(/obj/item/pda =10, - /obj/item/cartridge/mob_hunt_game = 25, /obj/item/cartridge/medical = 10, /obj/item/cartridge/chemistry = 10, /obj/item/cartridge/engineering = 10, @@ -1314,7 +1313,6 @@ /obj/item/cartridge/mime = 1) prices = list(/obj/item/pda = 300, - /obj/item/cartridge/mob_hunt_game = 50, /obj/item/cartridge/medical = 200, /obj/item/cartridge/chemistry = 150, /obj/item/cartridge/engineering = 100, diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 93332e05f69..c1d333e8c4a 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -16,8 +16,16 @@ wreckage = /obj/structure/mecha_wreckage/ripley var/list/cargo = new var/cargo_capacity = 15 + + /// How many goliath hides does the Ripley have? Does not stack with other armor var/hides = 0 + /// How many drake hides does the Ripley have? Does not stack with other armor + var/drake_hides = 0 + + /// How many plates does the Ripley have? Does not stack with other armor + var/plates = 0 + /obj/mecha/working/ripley/Move() . = ..() if(.) @@ -33,10 +41,14 @@ ore.forceMove(ore_box) /obj/mecha/working/ripley/Destroy() - for(var/i=1, i <= hides, i++) - new /obj/item/stack/sheet/animalhide/goliath_hide(loc) //If a goliath-plated ripley gets killed, all the plates drop + for(var/i in 1 to hides) + new /obj/item/stack/sheet/animalhide/goliath_hide(get_turf(src)) //If a armor-plated ripley gets killed, all the armor drop + for(var/i in 1 to plates) + new /obj/item/stack/sheet/animalhide/armor_plate(get_turf(src)) + for(var/i in 1 to drake_hides) + new /obj/item/stack/sheet/animalhide/ashdrake(get_turf(src)) for(var/atom/movable/A in cargo) - A.forceMove(loc) + A.forceMove(get_turf(src)) step_rand(A) cargo.Cut() return ..() @@ -55,22 +67,58 @@ /obj/mecha/working/ripley/update_desc() . = ..() - if(!hides) // Just in case if hides are somehow removed + if(!hides && !plates && !drake_hides) // Just in case if armor is removed desc = initial(desc) return - if(hides == 3) - desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - its pilot must be an experienced monster hunter." - else - desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates." + + // Goliath hides + if(hides) + if(hides == HIDES_COVERED_FULL) + desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - its pilot must be an experienced monster hunter." + else + desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates." + return + + // Metal plates + if(plates) + if(plates == PLATES_COVERED_FULL) + desc = "Autonomous Power Loader Unit. Its armor is completely lined with metal plating." + else + desc = "Autonomous Power Loader Unit. Its armor is reinforced with some metal plating." + return + + // Drake hides + if(drake_hides) + if(drake_hides == DRAKE_HIDES_COVERED_FULL) + desc = "Autonomous Power Loader Unit. Its every corner is covered in ancient hide, creating a powerful shield. The pilot of this exosuit must be prepared for battles on the level of legend." + if(drake_hides == DRAKE_HIDES_COVERED_MODERATE) + desc = "Autonomous Power Loader Unit. Its armor is adorned with dragon hide plates, instilling fear in its enemies and guarding its pilot." + if(drake_hides == DRAKE_HIDES_COVERED_SLIGHT) + desc = "Autonomous Power Loader Unit. The armor of this exosuit only touches the mythical: a few plates of dragon hide adorn its plating like rare warrior trophies." + return /obj/mecha/working/ripley/update_overlays() . = ..() - if(!hides) - return - if(hides == 3) - . += occupant ? "ripley-g-full" : "ripley-g-full-open" - else - . += occupant ? "ripley-g" : "ripley-g-open" +// hides + if(hides) + if(hides == HIDES_COVERED_FULL) + . += occupant ? "ripley-g-full" : "ripley-g-full-open" + else + . += occupant ? "ripley-g" : "ripley-g-open" +//plates + if(plates) + if(plates == PLATES_COVERED_FULL) + . += occupant ? "ripley-m-full" : "ripley-m-full-open" + else + . += occupant ? "ripley-m" : "ripley-m-open" +//drake hides + if(drake_hides) + if(drake_hides == DRAKE_HIDES_COVERED_FULL) + . += occupant ? "ripley-d-full" : "ripley-d-full-open" + else if(drake_hides == DRAKE_HIDES_COVERED_MODERATE) + . += occupant ? "ripley-d-2" : "ripley-d-2-open" + else if(drake_hides == DRAKE_HIDES_COVERED_SLIGHT) + . += occupant ? "ripley-d" : "ripley-d-open" /obj/mecha/working/ripley/firefighter desc = "A standard APLU chassis that was refitted with additional thermal protection and a cistern." diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm index 3e45148ef51..c9e7d99ac08 100644 --- a/code/game/mecha/working/working.dm +++ b/code/game/mecha/working/working.dm @@ -1,2 +1,3 @@ /obj/mecha/working internal_damage_threshold = 60 + diff --git a/code/game/objects/effects/decals/turfdecals/markings.dm b/code/game/objects/effects/decals/turfdecals/markings.dm index 433e4ef94c7..8ee39dae4a2 100644 --- a/code/game/objects/effects/decals/turfdecals/markings.dm +++ b/code/game/objects/effects/decals/turfdecals/markings.dm @@ -228,3 +228,6 @@ /obj/effect/turf_decal/raven/nine icon_state = "RAVEN9" + +/obj/effect/turf_decal/blue_corner + icon_state = "darkbluecorners" diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index a3b15f322a5..3247946bb39 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -19,41 +19,3 @@ for(var/j in 1 to steps_amt) sleep(1) step(expl,direct) - -/obj/effect/explosion - name = "explosive particles" - icon = 'icons/effects/96x96.dmi' - icon_state = "explosion" - opacity = TRUE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - pixel_x = -32 - pixel_y = -32 - -/obj/effect/explosion/New() - ..() - QDEL_IN(src, 10) - -/datum/effect_system/explosion - -/datum/effect_system/explosion/set_up(loca) - if(isturf(loca)) - location = loca - else - location = get_turf(loca) - -/datum/effect_system/explosion/start() - new/obj/effect/explosion(location) - var/datum/effect_system/expl_particles/P = new/datum/effect_system/expl_particles() - P.set_up(10, 0, location) - P.start() - -/datum/effect_system/explosion/smoke - -/datum/effect_system/explosion/smoke/proc/create_smoke() - var/datum/effect_system/smoke_spread/S = new - S.set_up(5, FALSE, location, null) - S.start() - -/datum/effect_system/explosion/smoke/start() - ..() - addtimer(CALLBACK(src, PROC_REF(create_smoke)), 5) diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index a87d2909654..374a2fb1114 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -678,8 +678,5 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/newplayer_start) //Without this you sp var/turf/simulated/T = get_turf(src) T.burn_tile() -/obj/effect/landmark/battle_mob_point - name = "Nanomob Battle Avatar Spawn Point" - /obj/effect/landmark/free_golem_spawn name = "Free Golem Spawn Point" diff --git a/code/game/objects/effects/temporary_visuals/explosion_temp_visuals.dm b/code/game/objects/effects/temporary_visuals/explosion_temp_visuals.dm new file mode 100644 index 00000000000..9b6b318758a --- /dev/null +++ b/code/game/objects/effects/temporary_visuals/explosion_temp_visuals.dm @@ -0,0 +1,64 @@ +/obj/effect/temp_visual/explosion + name = "boom" + icon = 'icons/effects/96x96.dmi' + icon_state = "explosion2" + duration = 6 SECONDS + /// Smoke wave particle holder + var/obj/effect/abstract/particle_holder/smoke_wave + /// Explosion smoke particle holder + var/obj/effect/abstract/particle_holder/explosion_smoke + /// Sparks particle holder + var/obj/effect/abstract/particle_holder/sparks + +/obj/effect/temp_visual/explosion/Initialize(mapload, radius, color, small = FALSE, large = FALSE) + . = ..() + set_light(radius, radius, LIGHT_COLOR_ORANGE) + generate_particles(radius, small, large) + var/image/I = image(icon, src, icon_state, 10, -32, -32) + var/matrix/rotate = matrix() + rotate.Turn(rand(0, 359)) + I.transform = rotate + overlays += I // We use an overlay so the explosion and light source are both in the correct location plus so the particles don't rotate with the explosion + icon_state = null + +/// Generate the particles +/obj/effect/temp_visual/explosion/proc/generate_particles(radius, small = FALSE, large = FALSE) + if(small) + smoke_wave = new(src, /particles/smoke_wave/small) + else + smoke_wave = new(src, /particles/smoke_wave) + + if(large) + explosion_smoke = new(src, /particles/explosion_smoke/deva) + else if(small) + explosion_smoke = new(src, /particles/explosion_smoke/small) + else + explosion_smoke = new(src, /particles/explosion_smoke) + + sparks = new(src, /particles/sparks_outwards) + + if(large) + smoke_wave.particles.velocity = generator(GEN_CIRCLE, 6 * radius, 6 * radius) + else if(small) + smoke_wave.particles.velocity = generator(GEN_CIRCLE, 3 * radius, 3 * radius) + else + smoke_wave.particles.velocity = generator(GEN_CIRCLE, 5 * radius, 5 * radius) + + explosion_smoke.layer = layer + 0.1 + sparks.particles.velocity = generator(GEN_CIRCLE, 8 * radius, 8 * radius) + + // The reason for these timers is to set the count to 0 + // This causes any particle systems to not spawn in new particles, but not delete the currently existing ones + addtimer(CALLBACK(src, PROC_REF(set_count_short)), 1 SECONDS) + +/obj/effect/temp_visual/explosion/proc/set_count_short() + remove_light() + explosion_smoke.particles.count = 0 + sparks.particles.count = 0 + smoke_wave.particles.count = 0 + +/obj/effect/temp_visual/explosion/Destroy() + QDEL_NULL(smoke_wave) + QDEL_NULL(explosion_smoke) + QDEL_NULL(sparks) + return ..() diff --git a/code/game/objects/effects/temporary_visuals/misc_visuals.dm b/code/game/objects/effects/temporary_visuals/misc_visuals.dm index 1a8a23ee937..77cdaa73bf4 100644 --- a/code/game/objects/effects/temporary_visuals/misc_visuals.dm +++ b/code/game/objects/effects/temporary_visuals/misc_visuals.dm @@ -231,16 +231,12 @@ layer = ABOVE_MOB_LAYER duration = 4 -/obj/effect/temp_visual/explosion +/obj/effect/temp_visual/pka_explosion name = "explosion" icon = 'icons/effects/96x96.dmi' - icon_state = "explosion" + icon_state = "explosionfast" pixel_x = -32 pixel_y = -32 - duration = 8 - -/obj/effect/temp_visual/explosion/fast - icon_state = "explosionfast" duration = 4 /obj/effect/temp_visual/heart diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index f549f5f8cd3..1c6b50e64fe 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,5 +1,3 @@ -//TODO: Flash range does nothing currently - #define CREAK_DELAY 5 SECONDS //Time taken for the creak to play after explosion, if applicable. #define DEVASTATION_PROB 30 //The probability modifier for devistation, maths! #define HEAVY_IMPACT_PROB 5 //ditto @@ -74,6 +72,10 @@ var/turf/M_turf = get_turf(M) if(M_turf && M_turf.z == z0) var/dist = get_dist(M_turf, epicenter) + if(isliving(M) && dist <= flash_range) + var/mob/living/to_flash = M + var/is_very_close_to_the_explosion = flash_range > (dist * 2) + to_flash.flash_eyes(is_very_close_to_the_explosion * 2, is_very_close_to_the_explosion, is_very_close_to_the_explosion) // Gets past sunglasses var/baseshakeamount if(orig_max_distance - dist > 0) baseshakeamount = sqrt((orig_max_distance - dist) * 0.1) @@ -107,14 +109,12 @@ if(creaking_explosion) // 5 seconds after the bang, the station begins to creak addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, playsound_local), epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), 1, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY) - if(heavy_impact_range > 1) - var/datum/effect_system/explosion/E - if(smoke) - E = new /datum/effect_system/explosion/smoke - else - E = new - E.set_up(epicenter) - E.start() + if(devastation_range > 0) + new /obj/effect/temp_visual/explosion(epicenter, max_range, FALSE, TRUE) + else if(heavy_impact_range > 0) + new /obj/effect/temp_visual/explosion(epicenter, max_range, FALSE, FALSE) + else if(light_impact_range > 0) + new /obj/effect/temp_visual/explosion(epicenter, max_range, TRUE, FALSE) var/list/affected_turfs = spiral_range_turfs(max_range, epicenter) diff --git a/code/game/objects/items/robot/cyborg_gripper.dm b/code/game/objects/items/robot/cyborg_gripper.dm new file mode 100644 index 00000000000..59409c56fa3 --- /dev/null +++ b/code/game/objects/items/robot/cyborg_gripper.dm @@ -0,0 +1,231 @@ +/* CONTENTS: +0. generic define gripper +1. UNIVERSAL GRIPPER +2. MEDICAL GRIPPER +3. SERVICE GRIPPER +4. ENGINEERING GRIPPER +*/ + +// Generic gripper. This should never appear anywhere. +/obj/item/gripper + name = "generic gripper item" + desc = "If you can see this, make an issue report to Github. Something has gone wrong!" + icon = 'icons/obj/device.dmi' + icon_state = "gripper" + actions_types = list(/datum/action/item_action/drop_gripped_item) + /// Set to TRUE to allow interaction with light fixtures and cell-containing machinery. + var/engineering_machine_interaction = FALSE + /// Set to TRUE to allow the gripper to shake people awake/help them up. + var/can_help_up = FALSE + /// Defines what items the gripper can carry. + var/list/can_hold = list() + /// Set to TRUE to allow ANY item to be held, bypassing can_hold checks. + var/can_hold_all_items = FALSE + /// The item currently being held. + var/obj/item/gripped_item + +/obj/item/gripper/examine(mob/user) + . = ..() + if(!gripped_item) + . += "[src] is empty." + return + . += "[src] is currently holding [gripped_item]." + +/obj/item/gripper/examine_more(mob/user) + . = ..() + . += {"Cyborg grippers are well-developed, and despite some anatomical differences that manifest in some models, they can be used just as effectively as a regular hand with enough practice. + +Companies like Nanotrasen use software to limit the items that a cyborg can manipulate to a specific pre-defined list, \ +as part of their multi-layered protections to try and eliminate the chance of a hypothetical synthetic uprising, not wishing to see a repeat of the IPC uprising in 2525."} + + +/obj/item/gripper/Initialize(mapload) + . = ..() + can_hold = typecacheof(can_hold) + +/obj/item/gripper/ui_action_click(mob/user) + drop_gripped_item(user) + +/obj/item/gripper/proc/drop_gripped_item(mob/user, silent = FALSE) + if(!gripped_item) + to_chat(user, "[src] is empty.") + return + if(!silent) + to_chat(user, "You drop [gripped_item].") + gripped_item.forceMove(get_turf(src)) + gripped_item = null + +/obj/item/gripper/attack_self(mob/user) + if(!gripped_item) + to_chat(user, "[src] is empty.") + return + gripped_item.attack_self(user) + +/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user) + return + +// This is required to ensure that the forceMove checks on some objects don't rip the gripper out of the borg's inventory and toss it on the floor. That would hurt, a lot! +/obj/item/gripper/forceMove(atom/destination) + return + +/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params) + //Target is invalid or we are not adjacent. + if(!target || !proximity) + return FALSE + // Shake people awake, get them on their feet. + if(ishuman(target) && can_help_up) + var/mob/living/carbon/human/pickup_target = target + if(!IS_HORIZONTAL(pickup_target)) + return + pickup_target.AdjustSleeping(-10 SECONDS) + pickup_target.AdjustParalysis(-6 SECONDS) + pickup_target.AdjustStunned(-6 SECONDS) + pickup_target.AdjustWeakened(-6 SECONDS) + pickup_target.AdjustKnockDown(-6 SECONDS) + pickup_target.adjustStaminaLoss(-10) + pickup_target.resting = FALSE + pickup_target.stand_up() + playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1) + user.visible_message( + "[user] shakes [pickup_target] trying to wake [pickup_target.p_them()] up!", + "You shake [pickup_target] trying to wake [pickup_target.p_them()] up!" + ) + return FALSE + //Already have an item. + if(gripped_item) + + //Pass the attack on to the target. This might delete/relocate gripped_item. + if(!target.attackby(gripped_item, user, params)) + // If the attackby didn't resolve or delete the target or gripped_item, afterattack + // (Certain things, such as mountable frames, rely on afterattack) + gripped_item?.afterattack(target, user, 1, params) + + //If gripped_item either didn't get deleted, or it failed to be transfered to its target + if(!gripped_item && length(contents)) + gripped_item = contents[1] + return FALSE + else if(gripped_item && !contents.len) + gripped_item = null + + //Check that we're not pocketing a mob. + else if(isitem(target)) + var/obj/item/I = target + // Make sure the item is something the gripper can hold + if(can_hold_all_items || is_type_in_typecache(I, can_hold)) + to_chat(user, "You collect [I].") + I.forceMove(src) + gripped_item = I + return TRUE + + to_chat(user, "You hold your gripper over [target], but no matter how hard you try, you cannot make yourself grab it.") + return FALSE + + // Everything past this point requires being able to engineer. + if(!engineering_machine_interaction) + return + // APC cells. + if(istype(target, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = target + if(A.opened && A.cell) + gripped_item = A.cell + + A.cell.add_fingerprint(user) + A.cell.update_icon() + A.cell.forceMove(src) + A.cell = null + + A.charging = APC_NOT_CHARGING + A.update_icon() + + user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.") + // Cell Chargers + else if(istype(target, /obj/machinery/cell_charger)) + var/obj/machinery/cell_charger/cell_charger = target + if(cell_charger.charging) + gripped_item = cell_charger.charging + cell_charger.charging.add_fingerprint(user) + cell_charger.charging.forceMove(src) + cell_charger.removecell() + // Putting lights in fixtures. + else if(istype(target, /obj/machinery/light)) + var/obj/machinery/light/light = target + var/obj/item/light/L = light.drop_light_tube() + L.forceMove(src) + gripped_item = L + user.visible_message("[user] removes the light from the fixture.", "You dislodge the light from the fixture.") + + return TRUE + +//////////////////////////////// +// MARK: UNIVERSAL GRIPPER +//////////////////////////////// +/// Universal gripper. Not supplied to any cyborg by default. Could be varedited onto a borg for event stuff. Functions almost like a real hand! +/obj/item/gripper/universal + name = "cyborg gripper" + desc = "A grasping tool for cyborgs. This one is not restricted by any restraining software, allowing it to handle any object the user wishes." + // It's UNIVERSAL so it has all functions enabled. + engineering_machine_interaction = TRUE + can_help_up = TRUE + can_hold_all_items = TRUE + +//////////////////////////////// +// MARK: MEDICAL GRIPPER +//////////////////////////////// +// For medical borgs, for doing medical stuff! +// Not giving this anything to hold yet, but stuff may be added in the future. Organs/implants are currently viewed as too strong to hold. +/obj/item/gripper/medical + name = "medical gripper" + desc = "A grasping tool for cyborgs. This one is covered with hygenic medical-grade silicone rubber. \ + Use it to help patients up once surgery is complete, or to substitute for hands in surgical operations." + can_help_up = TRUE + // REMOVE actions_types from here if you add a can_hold list for this gripper! + actions_types = list() + +//////////////////////////////// +// MARK: SERVICE GRIPPER +//////////////////////////////// +// For service borgs. To make them slightly better at their job. +/obj/item/gripper/service + name = "service gripper" + desc = "A grasping tool for cyborgs. This version is made from hygenic easy-clean material. Maybe some day you'll be able to grab food with it..." + // For waking up drunkards. + can_help_up = TRUE + // Everything in this list is currently for either playing games or otherwise assisting the crew in mundane, non-impactful ways. + can_hold = list( + /obj/item/deck, + /obj/item/cardhand, + /obj/item/coin, + /obj/item/paper, + /obj/item/photo, + /obj/item/toy/plushie + ) + +//////////////////////////////// +// MARK: ENGINEERING GRIPPER +//////////////////////////////// +// For engineering and sabotage borgs, and drones. +/obj/item/gripper/engineering + name = "engineering gripper" + desc = "A grasping tool for cyborgs. This version can hold a wide variety of constructon components for use in engineering work." + engineering_machine_interaction = TRUE + can_hold = list( + /obj/item/firealarm_electronics, + /obj/item/airalarm_electronics, + /obj/item/airlock_electronics, + /obj/item/firelock_electronics, + /obj/item/intercom_electronics, + /obj/item/apc_electronics, + /obj/item/tracker_electronics, + /obj/item/stock_parts, + /obj/item/vending_refill, + /obj/item/mounted/frame, + /obj/item/assembly/prox_sensor, + /obj/item/assembly/igniter, + /obj/item/rack_parts, + /obj/item/camera_assembly, + /obj/item/tank, + /obj/item/circuitboard, + /obj/item/stack/ore/bluespace_crystal, + /obj/item/stack/tile/light, + /obj/item/light + ) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 28cad65e92f..245656352e4 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -486,3 +486,24 @@ return for(var/obj/item/reagent_containers/borghypo/F in R.module.modules) F.emag_act() + +/obj/item/borg/upgrade/abductor_jani + name = "janitorial cyborg abductor upgrade" + desc = "An experimental upgrade that replaces a janitorial cyborg's tools with the abductor versions." + icon_state = "abductor_mod" + origin_tech = "biotech=6;materials=6;abductor=3" + require_module = TRUE + module_type = /obj/item/robot_module/janitor + items_to_replace = list( + /obj/item/mop/advanced/cyborg = /obj/item/mop/advanced/abductor, + /obj/item/soap = /obj/item/soap/syndie/abductor, + /obj/item/lightreplacer/cyborg = /obj/item/lightreplacer/bluespace/abductor, + /obj/item/melee/flyswatter = /obj/item/melee/flyswatter/abductor + ) + items_to_add = list( + /obj/item/reagent_containers/spray/cleaner/safety/abductor + ) + special_rechargables = list( + /obj/item/reagent_containers/spray/cleaner/safety/abductor, + /obj/item/lightreplacer/bluespace/abductor + ) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index f91e4b8d75b..266974088d2 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -178,7 +178,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( /obj/item/stack/sheet/animalhide/goliath_hide name = "goliath hide plates" - desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna." + desc = "Pieces of a goliath's rocky hide, these might be able to make your miner equipment such as suits, plasmaman helmets, borgs and Ripley class exosuits a bit more durable to attack from the local fauna." icon = 'icons/obj/stacks/organic.dmi' icon_state = "goliath_hide" item_state = "goliath_hide" @@ -198,41 +198,80 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( if(is_type_in_typecache(target, goliath_platable_armor_typecache)) var/obj/item/clothing/C = target var/datum/armor/current_armor = C.armor - if(current_armor.getRating(MELEE) < 60) - C.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 10, 60)) + if(current_armor.getRating(MELEE) < 75) + if(!use(1)) + to_chat(user, "You dont have enough [src] for this!") + return + C.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 15, 75)) to_chat(user, "You strengthen [target], improving its resistance against melee attacks.") use(1) else to_chat(user, "You can't improve [C] any further!") else if(istype(target, /obj/mecha/working/ripley)) var/obj/mecha/working/ripley/D = target - if(D.hides < 3) + if(D.hides < HIDES_COVERED_FULL && !D.plates && !D.drake_hides) + if(!use(1)) + to_chat(user, "You dont have enough [src] for this!") + return D.hides++ - D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 10, 70)) - D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 5, 50)) - D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 5, 50)) - to_chat(user, "You strengthen [target], improving its resistance against melee attacks.") + D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 25, 115)) + D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 7, 60)) + D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 7, 60)) + to_chat(user, "You strengthen [target], improving its resistance against attacks.") D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS) - use(1) else to_chat(user, "You can't improve [D] any further!") else if(isrobot(target)) var/mob/living/silicon/robot/R = target if(istype(R.module, /obj/item/robot_module/miner)) var/datum/armor/current_armor = R.armor - if(current_armor.getRating(MELEE) < 60) - R.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 10, 60)) + if(current_armor.getRating(MELEE) < 75) + if(!use(1)) + to_chat(user, "You dont have enough [src] for this!") + return + R.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 15, 75)) to_chat(user, "You strengthen [target], improving its resistance against melee attacks.") - use(1) else to_chat(user, "You can't improve [R] any further!") else to_chat(user, "[R]'s armor can not be improved!") +/obj/item/stack/sheet/animalhide/armor_plate + name = "armor plate" + desc = "This piece of metal can be attached to the mech itself, enhancing its protective characteristics. Unfortunately, only working class exosuits have notches for such armor." + icon = 'icons/mecha/mecha_equipment.dmi' + icon_state = "armor_plate" + item_state = "armor_plate" + singular_name = "armor plate" + flags = NOBLUDGEON + w_class = WEIGHT_CLASS_NORMAL + layer = MOB_LAYER + +/obj/item/stack/sheet/animalhide/armor_plate/afterattack(atom/target, mob/user, proximity_flag) + if(!proximity_flag) + return + if(istype(target, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/D = target + if(D.plates < PLATES_COVERED_FULL && !D.hides && !D.drake_hides) + if(!use(1)) + to_chat(user, "You dont have enough [src] for this!") + return + use(1) + D.plates++ + D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 10, 70)) + D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 4, 50)) + D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 4, 50)) + to_chat(user, "You strengthen [target], improving its resistance against attacks.") + D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS) + else + to_chat(user, "You can't improve [D] any further!") + +/obj/item/stack/sheet/animalhide/armor_plate/attackby(obj/item/W, mob/user, params) + return // no steel leather for ya /obj/item/stack/sheet/animalhide/ashdrake name = "ash drake hide" - desc = "The strong, scaled hide of an ash drake." + desc = "The strong, scaled hide of an ash drake. Can be attached to the mech itself, greatly enhancing its protective characteristics. Unfortunately, only working class exosuits have notches for such armor." icon = 'icons/obj/stacks/organic.dmi' icon_state = "dragon_hide" item_state = "dragon_hide" @@ -242,9 +281,30 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( layer = MOB_LAYER dynamic_icon_state = TRUE +/obj/item/stack/sheet/animalhide/ashdrake/afterattack(atom/target, mob/user, proximity_flag) + if(!proximity_flag) + return + if(istype(target, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/D = target + if(D.drake_hides < DRAKE_HIDES_COVERED_FULL && !D.hides && !D.plates) + if(!use(1)) + to_chat(user, "You dont have enough [src] for this!") + return + use(1) + D.drake_hides++ + D.max_integrity += 50 + D.obj_integrity += 50 + D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 45, 175)) // 77.7% melee armor maximum + D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 7, 60)) + D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 7, 60)) + to_chat(user, "You strengthen [target], improving its resistance against attacks.") + D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS) + else + to_chat(user, "You can't improve [D] any further!") + //Step one - dehairing. -/obj/item/stack/sheet/animalhide/attackby(obj/item/W as obj, mob/user as mob, params) +/obj/item/stack/sheet/animalhide/attackby(obj/item/W, mob/user, params) if(W.sharp) user.visible_message("[user] starts cutting hair off \the [src].", "You start cutting the hair off \the [src]...", "You hear the sound of a knife rubbing against flesh.") if(do_after(user, 50 * W.toolspeed, target = src)) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 206c971bd86..33a29c0fa15 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -215,6 +215,7 @@ GLOBAL_LIST_INIT(wood_recipes, list( new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 1 SECONDS), new /datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wooden, 3, time = 1 SECONDS), new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 10 SECONDS), + new /datum/stack_recipe("notice board", /obj/item/mounted/noticeboard, 5, time = 5 SECONDS), null, new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), new /datum/stack_recipe_list("wood structures", list( diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 4d58d09d211..c53a55e217a 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -35,16 +35,6 @@ toolspeed = 0.5 resistance_flags = FIRE_PROOF | ACID_PROOF -/obj/item/crowbar/abductor - name = "alien crowbar" - desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." - icon = 'icons/obj/abductor.dmi' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - icon_state = "crowbar" - toolspeed = 0.1 - w_class = WEIGHT_CLASS_SMALL - origin_tech = "combat=4;engineering=4;abductor=3" - /obj/item/crowbar/small name = "miniature titanium crowbar" desc = "A tiny, lightweight titanium crowbar. It fits handily in your pocket." diff --git a/code/game/objects/items/tools/multitool.dm b/code/game/objects/items/tools/multitool.dm index a44742ade66..080d58d57dc 100644 --- a/code/game/objects/items/tools/multitool.dm +++ b/code/game/objects/items/tools/multitool.dm @@ -171,19 +171,6 @@ . = ..() ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) // Drones are linked to the station -/obj/item/multitool/abductor - name = "alien multitool" - desc = "An omni-technological interface." - icon = 'icons/obj/abductor.dmi' - icon_state = "multitool" - toolspeed = 0.1 - w_class = WEIGHT_CLASS_SMALL - origin_tech = "magnets=5;engineering=5;abductor=3" - -/obj/item/multitool/abductor/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) - #undef PROXIMITY_NONE #undef PROXIMITY_ON_SCREEN #undef PROXIMITY_NEAR diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 6f0587188fa..b9a79fbcfdd 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -90,15 +90,6 @@ return BRUTELOSS -/obj/item/screwdriver/abductor - name = "alien screwdriver" - desc = "An ultrasonic screwdriver." - icon = 'icons/obj/abductor.dmi' - icon_state = "screwdriver" - usesound = 'sound/items/pshoom.ogg' - toolspeed = 0.1 - random_color = FALSE - /obj/item/screwdriver/power name = "hand drill" desc = "A simple hand drill with a screwdriver bit attached." diff --git a/code/game/objects/items/tools/welder.dm b/code/game/objects/items/tools/welder.dm index f4a03f9a632..239d13fd9a7 100644 --- a/code/game/objects/items/tools/welder.dm +++ b/code/game/objects/items/tools/welder.dm @@ -275,19 +275,6 @@ materials = list(MAT_METAL = 200, MAT_GLASS = 50) low_fuel_changes_icon = FALSE -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - w_class = WEIGHT_CLASS_SMALL - light_intensity = 0 - origin_tech = "plasmatech=5;engineering=5;abductor=3" - requires_fuel = FALSE - refills_over_time = TRUE - low_fuel_changes_icon = FALSE - /obj/item/weldingtool/hugetank name = "upgraded welding tool" desc = "An upgraded welder based off the industrial welder." diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm index f0b6f20aacc..7a2d0f8db30 100644 --- a/code/game/objects/items/tools/wirecutters.dm +++ b/code/game/objects/items/tools/wirecutters.dm @@ -98,19 +98,6 @@ random_color = FALSE resistance_flags = FIRE_PROOF | ACID_PROOF -/obj/item/wirecutters/abductor - name = "alien wirecutters" - desc = "Extremely sharp wirecutters, made out of a silvery-green metal." - icon = 'icons/obj/abductor.dmi' - icon_state = "cutters" - toolspeed = 0.1 - origin_tech = "materials=5;engineering=4;abductor=3" - random_color = FALSE - -/obj/item/wirecutters/abductor/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) - /obj/item/wirecutters/cyborg name = "wirecutters" desc = "This cuts wires." diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index 06188fd2244..64e9b3fe599 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -54,15 +54,6 @@ toolspeed = 0.5 resistance_flags = FIRE_PROOF | ACID_PROOF -/obj/item/wrench/abductor - name = "alien wrench" - desc = "A polarized wrench. It causes anything placed between the jaws to turn." - icon = 'icons/obj/abductor.dmi' - icon_state = "wrench" - usesound = 'sound/effects/empulse.ogg' - toolspeed = 0.1 - origin_tech = "materials=5;engineering=5;abductor=3" - /obj/item/wrench/power name = "hand drill" desc = "A simple powered drill with a bolt bit." diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 2306002dc48..a41b3295448 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -13,14 +13,19 @@ var/obj/item/assembly/nadeassembly = null var/assemblyattacher var/notify_admins = TRUE + /// C4 overlay to put on target + var/mutable_appearance/plastic_overlay + /// Target of the overlay, not neccicarly the thing the C4 is attached to! + var/atom/plastic_overlay_target /obj/item/grenade/plastic/Initialize(mapload) . = ..() - image_overlay = image('icons/obj/grenade.dmi', "[item_state]2") + plastic_overlay = mutable_appearance(icon, "[item_state]2", HIGH_OBJ_LAYER) /obj/item/grenade/plastic/Destroy() QDEL_NULL(nadeassembly) target = null + plastic_overlay_target = null return ..() /obj/item/grenade/plastic/attackby(obj/item/I, mob/user, params) @@ -74,7 +79,7 @@ return to_chat(user, "You start planting [src].[isnull(nadeassembly) ? " The timer is set to [det_time]..." : ""]") - if(do_after(user, 5 SECONDS * toolspeed, target = AM)) + if(do_after(user, 1.5 SECONDS * toolspeed, target = AM)) if(!user.unEquip(src)) return target = AM @@ -84,7 +89,26 @@ message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [det_time] second fuse", 0, 1) log_game("[key_name(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z]) with [det_time] second fuse") - AddComponent(/datum/component/persistent_overlay, image_overlay, target) + plastic_overlay.layer = HIGH_OBJ_LAYER + if(isturf(target) || istype(target, /obj/machinery/door)) + plastic_overlay_target = new /obj/effect/plastic(get_turf(user)) + else + plastic_overlay_target = target + if(isliving(target)) + plastic_overlay.layer = ABOVE_ALL_MOB_LAYER + if(plastic_overlay_target != target) + switch(plastic_overlay_target.x - target.x) + if(-1) + plastic_overlay.pixel_x += 32 + if(1) + plastic_overlay.pixel_x -= 32 + switch(plastic_overlay_target.y - target.y) + if(-1) + plastic_overlay.pixel_y += 32 + if(1) + plastic_overlay.pixel_y -= 32 + plastic_overlay_target.add_overlay(plastic_overlay) + if(!nadeassembly) to_chat(user, "You plant the bomb. Timer counting down from [det_time].") addtimer(CALLBACK(src, PROC_REF(prime)), det_time SECONDS) @@ -146,6 +170,10 @@ /obj/item/grenade/plastic/c4/prime() var/turf/location + if(plastic_overlay_target && !QDELETED(plastic_overlay_target)) + plastic_overlay_target.cut_overlay(plastic_overlay, TRUE) + if(istype(plastic_overlay_target, /obj/effect/plastic)) + qdel(plastic_overlay_target) if(target) if(!QDELETED(target)) location = get_turf(target) @@ -211,6 +239,10 @@ /obj/item/grenade/plastic/c4/thermite/prime() var/turf/location + if(plastic_overlay_target && !QDELETED(plastic_overlay_target)) + plastic_overlay_target.cut_overlay(plastic_overlay, TRUE) + if(istype(plastic_overlay_target, /obj/effect/plastic)) + qdel(plastic_overlay_target) if(target) if(!QDELETED(target)) location = get_turf(target) @@ -235,3 +267,7 @@ M.adjust_fire_stacks(2) M.IgniteMob() qdel(src) + +//Used so the effect is visable for overlay purposes, but not show on right click with a broken sprite +/obj/effect/plastic + mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 9d11690e376..0750631f1ba 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -457,22 +457,6 @@ new /obj/item/grenade/empgrenade(src) // Two of each new /obj/item/grenade/syndieminibomb(src) // One minibomb -/obj/item/storage/belt/military/abductor - name = "agent belt" - desc = "A belt used by abductor agents." - icon = 'icons/obj/abductor.dmi' - icon_state = "belt" - item_state = "security" - -/obj/item/storage/belt/military/abductor/full/populate_contents() - new /obj/item/screwdriver/abductor(src) - new /obj/item/wrench/abductor(src) - new /obj/item/weldingtool/abductor(src) - new /obj/item/crowbar/abductor(src) - new /obj/item/wirecutters/abductor(src) - new /obj/item/multitool/abductor(src) - new /obj/item/stack/cable_coil(src, 30, COLOR_WHITE) - /obj/item/storage/belt/military/assault name = "assault belt" desc = "A tactical assault belt." diff --git a/code/game/objects/mail.dm b/code/game/objects/mail.dm index 6e23945bb58..2f2eec45cf9 100644 --- a/code/game/objects/mail.dm +++ b/code/game/objects/mail.dm @@ -242,6 +242,8 @@ origin_tech = "magnets=1" /// The reference to the envelope that is currently stored in the mail scanner. It will be cleared upon confirming a correct delivery var/obj/item/envelope/saved + /// How far away can the scanner scan mail or people + var/scanner_range = 7 /obj/item/mail_scanner/examine(mob/user) . = ..() @@ -251,6 +253,9 @@ return /obj/item/mail_scanner/afterattack(atom/A, mob/user) + if(get_dist(A, user) > scanner_range) + to_chat(user, "The scanner doesn't reach that far!") + return if(istype(A, /obj/item/envelope)) var/obj/item/envelope/envelope = A if(envelope.has_been_scanned) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 151e2c22692..d7b37140b43 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -57,8 +57,9 @@ break // Fix for #383 - C4 deleting fridges with corpses -/obj/structure/closet/Destroy() - dump_contents() +/obj/structure/closet/Destroy(force) + if(!force) + dump_contents() return ..() /obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0) diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index 0be43090cc9..9d177ce3576 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -20,6 +20,7 @@ L.unbuckle_mob() L.forceMove(src) ADD_TRAIT(L, TRAIT_MUTE, STATUE_MUTE) + ADD_TRAIT(L, TRAIT_EMOTE_MUTE, STATUE_MUTE) max_integrity = max(L.health + 100, 100) //stoning damaged mobs will result in easier to shatter statues intialTox = L.getToxLoss() intialFire = L.getFireLoss() @@ -50,6 +51,7 @@ M.adjustFireLoss(intialFire - M.getFireLoss()) M.adjustBruteLoss(intialBrute - M.getBruteLoss()) M.setOxyLoss(intialOxy) + M.Stun(2.5 SECONDS) // No using items inside a statue if(timer <= 0) dump_contents() STOP_PROCESSING(SSobj, src) @@ -69,6 +71,7 @@ for(var/mob/living/M in src) M.forceMove(loc) REMOVE_TRAIT(M, TRAIT_MUTE, STATUE_MUTE) + REMOVE_TRAIT(M, TRAIT_EMOTE_MUTE, STATUE_MUTE) M.take_overall_damage((M.health - obj_integrity - 100),0) //any new damage the statue incurred is transfered to the mob ..() @@ -120,7 +123,7 @@ /obj/structure/closet/statue/indestructible resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - timer = 240 SECONDS_TO_LIFE_CYCLES + timer = 120 SECONDS_TO_LIFE_CYCLES /obj/structure/closet/statue/indestructible/ex_act(severity) return //No delimbing them diff --git a/code/game/objects/structures/depot_structures.dm b/code/game/objects/structures/depot_structures.dm index 42ace74d7f0..4d3a1919a49 100644 --- a/code/game/objects/structures/depot_structures.dm +++ b/code/game/objects/structures/depot_structures.dm @@ -113,7 +113,7 @@ M.gib() for(var/obj/mecha/E in range(30, T)) E.take_damage(E.max_integrity) - explosion(get_turf(src), 25, 35, 45, 55, 1, 1, 60, 0, 0) + explosion(get_turf(src), 25, 35, 45, 55, 1, 1, 60, 0) STOP_PROCESSING(SSobj, src) qdel(src) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index dc855f327fc..d094f279d63 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -90,7 +90,7 @@ else if(mybag) mybag.attackby(I, user, params) else - to_chat(usr, "You cannot interface your modules [src]!") + to_chat(usr, "You cannot interface your modules with [src]!") /obj/structure/janitorialcart/crowbar_act(mob/living/user, obj/item/I) . = TRUE diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index 5317afba5e9..1a5d501f77a 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -24,6 +24,9 @@ return ..() /obj/structure/mopbucket/attackby(obj/item/W as obj, mob/user as mob, params) + if(W.is_robot_module()) + to_chat(user, "You cannot interface your modules with [src]!") + return if(istype(W, /obj/item/mop)) var/obj/item/mop/M = W if(M.reagents.total_volume < M.reagents.maximum_volume) diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 6666de7ee61..eeb179d870d 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -1,82 +1,143 @@ +#define MAX_NOTICES 5 + +/obj/item/mounted/noticeboard + name = "notice board" + desc = "A board for pinning important notices upon." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "noticeboard" + w_class = WEIGHT_CLASS_BULKY + +/obj/item/mounted/noticeboard/do_build(turf/on_wall, mob/user) + new /obj/structure/noticeboard(get_turf(user), get_dir(on_wall, user), building = TRUE) + qdel(src) + /obj/structure/noticeboard name = "notice board" desc = "A board for pinning important notices upon." icon = 'icons/obj/stationobjs.dmi' - icon_state = "nboard00" + icon_state = "noticeboard-5" density = FALSE anchored = TRUE max_integrity = 150 var/notices = 0 -/obj/structure/noticeboard/Initialize() - ..() - for(var/obj/item/I in loc) - if(notices > 4) break - if(istype(I, /obj/item/paper)) - I.loc = src - notices++ - icon_state = "nboard0[notices]" +/obj/structure/noticeboard/New(turf/loc, direction, building = FALSE) + . = ..() + if(building) + setDir(direction) + set_pixel_offsets_from_dir(-32, 32, -30, 30) + update_icon(UPDATE_ICON_STATE) -//attaching papers!! -/obj/structure/noticeboard/attackby(obj/item/O as obj, mob/user as mob, params) - if(istype(O, /obj/item/paper)) - if(notices < 5) - O.add_fingerprint(user) - add_fingerprint(user) - user.drop_item() - O.loc = src +/obj/structure/noticeboard/Initialize() + . = ..() + for(var/obj/item/paper in loc) + if(notices >= MAX_NOTICES) + break + if(istype(paper, /obj/item/paper)) + paper.loc = src notices++ - icon_state = "nboard0[notices]" //update sprite - to_chat(user, "You pin the paper to the noticeboard.") - else - to_chat(user, "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.") + update_icon(UPDATE_ICON_STATE) + +/obj/structure/noticeboard/update_icon_state() + if(notices) + icon_state = "noticeboard-[notices]" return + icon_state = "noticeboard" + +/obj/structure/noticeboard/attack_hand(mob/user) + ui_interact(user) + +/obj/structure/noticeboard/attack_ghost(mob/user) + ui_interact(user) + +/obj/structure/noticeboard/ui_state(mob/user) + return GLOB.default_state + +/obj/structure/noticeboard/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Noticeboard", name) + ui.set_autoupdate(FALSE) + ui.open() + +/obj/structure/noticeboard/ui_data(mob/user) + var/list/data = list() + + var/list/pinned_papers = list() + for(var/obj/item/paper/paper in src) + pinned_papers += list(list( + "name" = paper.name, + "contents" = paper.info, + "ref" = paper.UID(), + )) + data["papers"] = pinned_papers + + return data + +/obj/structure/noticeboard/ui_act(action, params, datum/tgui/ui) + if(..()) + return + . = TRUE + + add_fingerprint(usr) + switch(action) + if("interact") + if(usr.stat || usr.restrained()) + return + var/obj/item/paper/paper = locate(params["paper"]) + if(!paper && paper.loc != src) + return + var/obj/item/held_item = usr.get_active_hand() + if(is_pen(held_item)) + paper.attackby(held_item, usr) + return + else + usr.put_in_hands(paper) + paper.add_fingerprint(usr) + notices-- + to_chat(usr, "You take a [paper.name] out of [src].") + update_icon(UPDATE_ICON_STATE) + if("showFull") + var/obj/item/paper/paper = locate(params["paper"]) + if(!paper && paper.loc != src) + return + paper.show_content(usr) + return + +/obj/structure/noticeboard/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/paper)) + if(notices >= MAX_NOTICES) + to_chat(user, "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.") + return + if(!user.drop_item()) + return + I.forceMove(src) + notices++ + to_chat(user, "You pin the paper to the noticeboard.") + update_icon(UPDATE_ICON_STATE) + add_fingerprint(user) + SStgui.update_uis(src) + return + return ..() -/obj/structure/noticeboard/attack_hand(user as mob) - var/dat = "Noticeboard
" - for(var/obj/item/paper/P in src) - dat += "[P.name] Write Remove
" - user << browse("Notices[dat]","window=noticeboard") - onclose(user, "noticeboard") +/obj/structure/noticeboard/wrench_act(mob/living/user, obj/item/I) + if(user.a_intent != INTENT_HELP) + return + . = TRUE + if(!(flags & NODECONSTRUCT)) + WRENCH_UNANCHOR_WALL_MESSAGE + I.play_tool_sound(user, I.tool_volume) + deconstruct(TRUE) /obj/structure/noticeboard/deconstruct(disassembled = TRUE) - if(!(flags & NODECONSTRUCT)) - new /obj/item/stack/sheet/metal (loc, 1) + if(flags & NODECONSTRUCT) + return + if(notices) + for(var/I in contents) + var/obj/item/paper/notice = I + notice.forceMove(loc) + new /obj/item/mounted/noticeboard(loc) qdel(src) -/obj/structure/noticeboard/Topic(href, href_list) - ..() - usr.set_machine(src) - if(href_list["remove"]) - if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open - return - var/obj/item/P = locate(href_list["remove"]) - if(P && P.loc == src) - P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck - P.add_fingerprint(usr) - add_fingerprint(usr) - notices-- - icon_state = "nboard0[notices]" - - if(href_list["write"]) - if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open - return - var/obj/item/P = locate(href_list["write"]) - - if((P && P.loc == src)) //ifthe paper's on the board - if(is_pen(usr.r_hand)) //and you're holding a pen - add_fingerprint(usr) - P.attackby(usr.r_hand, usr) //then do ittttt - else - if(is_pen(usr.l_hand)) //check other hand for pen - add_fingerprint(usr) - P.attackby(usr.l_hand, usr) - else - to_chat(usr, "You'll need something to write with!") - - if(href_list["read"]) - var/obj/item/paper/P = locate(href_list["read"]) - if(P && P.loc == src) - P.show_content(usr) - return +#undef MAX_NOTICES diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index 5cff309495b..ddfc3b8fb64 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -33,6 +33,11 @@ STOP_PROCESSING(SSobj, src) return ..() +/obj/structure/transit_tube/station/examine(mob/user) + . = ..() + . += "While in transit, hold the directional key matching the pod's direction to skip a station." + . += "While at a station, press a directional key to quickly leave the station in that direction." + /obj/structure/transit_tube/station/init_tube_dirs() // Tube station directions are simply 90 to either side of // the exit. @@ -47,7 +52,19 @@ tube_dirs = list(NORTH, SOUTH) boarding_dir = reverse_direction(dir) -/obj/structure/transit_tube/station/should_stop_pod(pod, from_dir) +/obj/structure/transit_tube/station/should_stop_pod(obj/structure/transit_tube_pod/pod, from_dir) + for(var/atom/atom in pod.contents) + var/client/client = CLIENT_FROM_VAR(atom) + if(!client) + return + + for(var/held_key in client.input_data.keys_held) + if(held_key in client.movement_kb_dirs) + var/held_dir = client.movement_kb_dirs[held_key] + // if they're holding a different direction down, + // stop to let them get out/change direction + return held_dir != from_dir + return TRUE /obj/structure/transit_tube/station/Bumped(mob/living/L) @@ -187,6 +204,9 @@ reverse_launch = TRUE uninstalled_type = /obj/structure/transit_tube_construction/terminus +/obj/structure/transit_tube/station/reverse/should_stop_pod(obj/structure/transit_tube_pod/pod, from_dir) + return TRUE + /obj/structure/transit_tube/station/reverse/init_tube_dirs() tube_dirs = list(turn(dir, -90)) boarding_dir = reverse_direction(dir) @@ -260,6 +280,9 @@ base_icon_state = "terminusdispenser0" uninstalled_type = /obj/structure/transit_tube_construction/terminus/dispenser +/obj/structure/transit_tube/station/dispenser/reverse/should_stop_pod(obj/structure/transit_tube_pod/pod, from_dir) + return TRUE + /obj/structure/transit_tube/station/dispenser/reverse/init_tube_dirs() tube_dirs = list(turn(dir, -90)) boarding_dir = reverse_direction(dir) diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm index aad4e103818..ad0fbabd901 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube.dm @@ -58,7 +58,7 @@ return // Called to check if a pod should stop upon entering this tube. -/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir) +/obj/structure/transit_tube/proc/should_stop_pod(obj/structure/transit_tube_pod/pod, from_dir) return FALSE // Called when a pod stops in this tube section. @@ -274,18 +274,3 @@ tube_dirs = list(EAST, NORTHWEST, SOUTHWEST) if(WEST) tube_dirs = list(WEST, SOUTHEAST, NORTHEAST) - - -// cosmetic "cap" for tubes. Note that tubes can't enter this. -/obj/structure/transit_tube/cap - icon_state = "cap" - -/obj/structure/transit_tube/cap/init_tube_dirs() - tube_dirs = list(turn(dir, 180)) // back the way we came - -/obj/structure/transit_tube/cap/has_entrance(from_dir) - return FALSE - -/obj/structure/transit_tube/cap/create_tube_overlay() - // cap sprites already have overlays - return diff --git a/code/game/turfs/simulated/floor/asteroid_floors.dm b/code/game/turfs/simulated/floor/asteroid_floors.dm index 440f2643f92..aadfe6c447a 100644 --- a/code/game/turfs/simulated/floor/asteroid_floors.dm +++ b/code/game/turfs/simulated/floor/asteroid_floors.dm @@ -146,16 +146,16 @@ ///////Surface. The surface is warm, but survivable without a suit. Internals are required. The floors break to chasms, which drop you into the underground. /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE baseturf = /turf/simulated/floor/lava/mapping_lava /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface_hard - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE color = COLOR_FLOOR_HARD_ROCK baseturf = /turf/simulated/floor/lava/lava_land_surface @@ -199,9 +199,9 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me data_having_type = /turf/simulated/floor/plating/asteroid/airless/cave/volcanic/has_data turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE /// subtype for producing a tunnel with given data /turf/simulated/floor/plating/asteroid/airless/cave/volcanic/has_data diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm index b157d90ce11..ffacfcf3ea8 100644 --- a/code/game/turfs/simulated/floor/chasm.dm +++ b/code/game/turfs/simulated/floor/chasm.dm @@ -173,9 +173,9 @@ drop_z = z - 1 /turf/simulated/floor/chasm/straight_down/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE baseturf = /turf/simulated/floor/chasm/straight_down/lava_land_surface //Chasms should not turn into lava light_range = 2 diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index d50da939c83..310b171bc0c 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -17,7 +17,7 @@ if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return remove_tile(user, FALSE, FALSE) - + /turf/simulated/floor/wood/get_broken_states() return list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") @@ -53,9 +53,9 @@ temperature = 180 /turf/simulated/floor/wood/lavaland_air - nitrogen = 14 - oxygen = 8 - temperature = 500 + nitrogen = LAVALAND_NITROGEN + oxygen = LAVALAND_OXYGEN + temperature = LAVALAND_TEMPERATURE // Grass /turf/simulated/floor/grass diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm index 6d43bd23a86..43b99723b42 100644 --- a/code/game/turfs/simulated/floor/indestructible.dm +++ b/code/game/turfs/simulated/floor/indestructible.dm @@ -44,9 +44,9 @@ icon = 'icons/turf/floors.dmi' icon_state = "necro1" baseturf = /turf/simulated/floor/indestructible/necropolis - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE footstep = FOOTSTEP_LAVA barefootstep = FOOTSTEP_LAVA @@ -69,9 +69,9 @@ icon = 'icons/turf/floors/boss_floors.dmi' icon_state = "boss" baseturf = /turf/simulated/floor/indestructible/boss - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE /turf/simulated/floor/indestructible/boss/air @@ -83,9 +83,9 @@ name = "floor" icon = 'icons/turf/floors/hierophant_floor.dmi' icon_state = "floor" - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE smoothing_flags = SMOOTH_CORNERS diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm index 8d32d83a35e..08ec20fb8f7 100644 --- a/code/game/turfs/simulated/floor/lava.dm +++ b/code/game/turfs/simulated/floor/lava.dm @@ -160,9 +160,9 @@ return /turf/simulated/floor/lava/lava_land_surface - temperature = 500 - oxygen = 8 - nitrogen = 14 + temperature = LAVALAND_TEMPERATURE + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN planetary_atmos = TRUE baseturf = /turf/simulated/floor/chasm/straight_down/lava_land_surface @@ -256,9 +256,9 @@ icon_state = "mappinglava" base_icon_state = "mappinglava" baseturf = /turf/simulated/floor/lava/mapping_lava - temperature = 500 - oxygen = 8 - nitrogen = 14 + temperature = LAVALAND_TEMPERATURE + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN planetary_atmos = TRUE diff --git a/code/game/turfs/simulated/floor/mineral_floors.dm b/code/game/turfs/simulated/floor/mineral_floors.dm index f1fb94e507f..aa6ea18b283 100644 --- a/code/game/turfs/simulated/floor/mineral_floors.dm +++ b/code/game/turfs/simulated/floor/mineral_floors.dm @@ -287,6 +287,6 @@ return //unburnable /turf/simulated/floor/plating/abductor/lavaland_air - temperature = 500 - oxygen = 8 - nitrogen = 14 + temperature = LAVALAND_TEMPERATURE + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 5bd564b6b78..01452e74990 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -4,9 +4,9 @@ smoothing_flags = NONE /turf/simulated/floor/vault/lavaland_air - temperature = 500 - oxygen = 8 - nitrogen = 14 + temperature = LAVALAND_TEMPERATURE + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN planetary_atmos = TRUE baseturf = /turf/simulated/floor/chasm/straight_down/lava_land_surface @@ -146,9 +146,9 @@ return /turf/simulated/floor/noslip/lavaland - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE /turf/simulated/floor/lubed @@ -234,9 +234,9 @@ uses_overlay = FALSE /turf/simulated/floor/clockwork/lavaland_air - nitrogen = 14 - oxygen = 8 - temperature = 500 + nitrogen = LAVALAND_NITROGEN + oxygen = LAVALAND_OXYGEN + temperature = LAVALAND_TEMPERATURE /turf/simulated/floor/catwalk name = "catwalk" diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 6fd8d12ffed..61b11391ba6 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -170,9 +170,9 @@ name = "plating" /turf/simulated/floor/plating/lavaland_air - temperature = 500 - oxygen = 8 - nitrogen = 14 + temperature = LAVALAND_TEMPERATURE + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN /turf/simulated/floor/engine name = "reinforced floor" @@ -253,9 +253,9 @@ return /turf/simulated/floor/engine/cult/lavaland_air - nitrogen = 14 - oxygen = 8 - temperature = 500 + nitrogen = LAVALAND_NITROGEN + oxygen = LAVALAND_OXYGEN + temperature = LAVALAND_TEMPERATURE //air filled floors; used in atmos pressure chambers diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index a090a32cbcf..9116c66a534 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -280,9 +280,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/lava/mapping_lava - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 mineralSpawnChanceList = list( /turf/simulated/mineral/uranium/volcanic = 35, /turf/simulated/mineral/diamond/volcanic = 30, /turf/simulated/mineral/gold/volcanic = 45, /turf/simulated/mineral/titanium/volcanic = 45, @@ -300,9 +300,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/lava/mapping_lava - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 mineralChance = 10 @@ -329,9 +329,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/lava/mapping_lava - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 mineralSpawnChanceList = list( /turf/simulated/mineral/uranium/volcanic = 3, /turf/simulated/mineral/diamond/volcanic = 1, /turf/simulated/mineral/gold/volcanic = 8, /turf/simulated/mineral/titanium/volcanic = 8, @@ -349,9 +349,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/uranium @@ -364,9 +364,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/diamond @@ -379,9 +379,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/gold @@ -394,9 +394,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/silver @@ -409,9 +409,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/titanium @@ -424,9 +424,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/plasma @@ -439,9 +439,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/clown @@ -455,9 +455,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/mime @@ -470,9 +470,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/bscrystal @@ -486,18 +486,18 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 /turf/simulated/mineral/volcanic environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt baseturf = /turf/simulated/floor/plating/asteroid/basalt - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE /turf/simulated/mineral/volcanic/lava_land_surface environment_type = "basalt" @@ -570,7 +570,7 @@ var/turf/bombturf = get_turf(src) mineralAmt = 0 stage = GIBTONITE_DETONATE - explosion(bombturf,1,3,5, adminlog = notify_admins) + explosion(bombturf, 1, 3, 5, adminlog = notify_admins) /turf/simulated/mineral/gibtonite/proc/defuse() if(stage == GIBTONITE_ACTIVE) @@ -610,9 +610,9 @@ environment_type = "basalt" turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface - oxygen = 8 - nitrogen = 14 - temperature = 500 + oxygen = LAVALAND_OXYGEN + nitrogen = LAVALAND_NITROGEN + temperature = LAVALAND_TEMPERATURE defer_change = 1 #undef GIBTONITE_UNSTRUCK diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 680cd80c053..bf588993722 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -369,8 +369,8 @@ if(try_wallmount(I, user, params)) return - // The magnetic gripper does a separate attackby, so bail from this one - if(istype(I, /obj/item/gripper_engineering)) + // The cyborg gripper does a separate attackby, so bail from this one + if(istype(I, /obj/item/gripper)) return return ..() diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index e667cfb2314..fd8502e8ef1 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -1,6 +1,6 @@ /turf/simulated/wall/mineral name = "mineral wall" - desc = "This shouldn't exist" + desc = "If you can see this, please make an issue report on GitHub." icon_state = "" smoothing_flags = SMOOTH_BITMASK canSmoothWith = null @@ -310,6 +310,9 @@ /turf/simulated/wall/mineral/titanium/nodecon/welder_act() return +/turf/simulated/wall/mineral/titanium/nodecon/try_destroy() + return + /////////////////////Plastitanium walls///////////////////// /turf/simulated/wall/mineral/plastitanium diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0b9abc3abf3..baf89390823 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -169,7 +169,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/debug_timers, /client/proc/force_verb_bypass, /client/proc/show_gc_queues, - /client/proc/debug_global_variables + /client/proc/debug_global_variables, + /client/proc/profile_code )) GLOBAL_LIST_INIT(admin_verbs_possess, list( /proc/possess, @@ -236,7 +237,8 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list( /client/proc/debug_global_variables, /client/proc/visualise_active_turfs, /client/proc/debug_timers, - /client/proc/timer_log + /client/proc/timer_log, + /client/proc/profile_code )) /client/proc/add_admin_verbs() @@ -955,6 +957,12 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list( src.stat_panel.send_message("create_debug") +/client/proc/profile_code() + set name = "Profile Code" + set category = "Debug" + + winset(usr, null, "command=.profile") + /client/proc/export_current_character() set name = "Export Character DMI/JSON" set category = "Admin" diff --git a/code/modules/admin/reagents_editor.dm b/code/modules/admin/reagents_editor.dm new file mode 100644 index 00000000000..058bff14336 --- /dev/null +++ b/code/modules/admin/reagents_editor.dm @@ -0,0 +1,103 @@ +/datum/reagents_editor + var/atom/target + /// Indexed by target.UID + var/static/list/datum/reagents_editor/editors = list() + +/datum/reagents_editor/New(atom/target) + src.target = target + +/datum/reagents_editor/ui_state(mob/user) + return GLOB.admin_state + +/datum/reagents_editor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ReagentsEditor") + ui.open() + ui.set_autoupdate(FALSE) + +/datum/reagents_editor/ui_close(mob/user) + var/open_uis = SStgui.open_uis_by_src[src.UID()] + if(isnull(open_uis) || !islist(open_uis) || length(open_uis) <= 1) + // Remove after everyone closes UI to avoid memory leak + editors -= target.UID() + +/datum/reagents_editor/ui_static_data(mob/user) + . = ..() + + var/list/reagents_information = list() + .["reagentsInformation"] = reagents_information + for(var/id in GLOB.chemical_reagents_list) + var/datum/reagent/R = GLOB.chemical_reagents_list[id] + reagents_information[id] = list( + "name" = R.name, + ) + +/datum/reagents_editor/ui_data(mob/user) + . = ..() + + var/list/reagents = list() + .["reagents"] = reagents + for(var/datum/reagent/R in target.reagents.reagent_list) + reagents[R.id] = list( + "volume" = R.volume, + "uid" = R.UID(), + ) + +// This interface intentionally emulates VV. +// It should, therefore, doesn't place restrictions on any actions, which includes but +// is not limited to: adding a reagent which overfills the container and adding blood +// with a non-existent blood type. It may also do things unconventionally, such as +// directly appending reagents to the list rather than using reagents.add_reagent to +// bypass reagent reactions. +/datum/reagents_editor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + + if(.) + return + + . = TRUE + + switch(action) + if("add_reagent") + var/reagent_id = params["reagentID"] + var/datum/reagent/reagent_prototype = GLOB.chemical_reagents_list[reagent_id] + if(isnull(reagent_prototype)) + return FALSE + var/new_volume = tgui_input_number(ui.user, "How much units of the reagent do you want to add?", "Add Reagent", 0, 1E100, -1E100) + var/datum/reagent/reagent = target.reagents.get_reagent_by_id(reagent_id) + if(isnull(reagent)) + reagent = new reagent_prototype.type() + reagent.holder = target.reagents + reagent.on_new() + if(ishuman(target) && target.reagents.can_metabolize(target, reagent)) + reagent.on_mob_add(target) + target.reagents.reagent_list += reagent + + reagent.volume = new_volume + + if("edit_volume") + var/reagent_uid = params["uid"] + var/datum/reagent/reagent = locateUID(reagent_uid) + if(isnull(reagent)) + return FALSE + var/new_volume = tgui_input_number(ui.user, "How much units of the reagent do you want to be in the container?", "Edit Reagent Volume", 0, 1E100, -1E100) + if(isnull(new_volume)) + return + reagent.volume = new_volume + + if("delete_reagent") + var/reagent_uid = params["uid"] + var/datum/reagent/reagent = locateUID(reagent_uid) + if(isnull(reagent)) + return FALSE + target.reagents.reagent_list -= reagent + + if("update_total") + target.reagents.update_total() + + if("react_reagents") + target.reagents.handle_reactions() + + else + . = FALSE diff --git a/code/modules/admin/sql_notes.dm b/code/modules/admin/sql_notes.dm index ef0253f972a..35da1e5dcbf 100644 --- a/code/modules/admin/sql_notes.dm +++ b/code/modules/admin/sql_notes.dm @@ -112,7 +112,8 @@ adminckey = query_find_note_del.item[3] qdel(query_find_note_del) - var/datum/db_query/query_del_note = SSdbcore.NewQuery("DELETE FROM notes WHERE id=:note_id", list( + var/datum/db_query/query_del_note = SSdbcore.NewQuery("UPDATE notes SET deleted=1, deletedby=:ckey WHERE id=:note_id", list( + "ckey" = usr.ckey, "note_id" = note_id )) if(!query_del_note.warn_execute()) @@ -193,7 +194,7 @@ var/target_sql_ckey = ckey(target_ckey) var/datum/db_query/query_get_notes = SSdbcore.NewQuery({" SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime, round_id, automated - FROM notes WHERE ckey=:targetkey ORDER BY timestamp"}, list( + FROM notes WHERE ckey=:targetkey AND deleted=0 ORDER BY timestamp"}, list( "targetkey" = target_sql_ckey )) if(!query_get_notes.warn_execute()) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index b945dca68e4..cdbce0a63d8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2062,6 +2062,7 @@ ptypes += "Shamebrero" ptypes += "Nugget" ptypes += "Bread" + ptypes += "Rod" var/punishment = input(owner, "How would you like to smite [M]?", "Its good to be baaaad...", "") as null|anything in ptypes if(!(punishment in ptypes)) return @@ -2185,7 +2186,6 @@ to_chat(H, "You feel as if your limbs are being ripped from your body!") addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/carbon/human, make_nugget)), 6 SECONDS) logmsg = "nugget" - if("Bread") var/mob/living/simple_animal/shade/sword/bread/breadshade = new(H.loc) var/bready = pick(/obj/item/food/snacks/customizable/cook/bread, /obj/item/food/snacks/sliceable/meatbread, /obj/item/food/snacks/sliceable/xenomeatbread, /obj/item/food/snacks/sliceable/spidermeatbread, /obj/item/food/snacks/sliceable/bananabread, /obj/item/food/snacks/sliceable/tofubread, /obj/item/food/snacks/sliceable/bread, /obj/item/food/snacks/sliceable/creamcheesebread, /obj/item/food/snacks/sliceable/banarnarbread, /obj/item/food/snacks/flatbread, /obj/item/food/snacks/baguette) @@ -2196,6 +2196,13 @@ qdel(H) logmsg = "baked" to_chat(breadshade, "Get bready for combat, you've been baked into a piece of bread! Before you break down and rye thinking that your life is over, people are after you waiting for a snack! If you'd rather not be toast, lunge away from any hungry crew else you bite the crust. At the yeast you may survive a little longer...") + if("Rod") + + var/starting_turf_x = M.x + rand(10, 15) * pick(1, -1) + var/starting_turf_y = M.y + rand(10, 15) * pick(1, -1) + var/turf/start = locate(starting_turf_x, starting_turf_y, M.z) + + new /obj/effect/immovablerod/smite(start, M) if(logmsg) log_admin("[key_name(owner)] smited [key_name(M)] with: [logmsg]") message_admins("[key_name_admin(owner)] smited [key_name_admin(M)] with: [logmsg]") diff --git a/code/modules/antagonists/changeling/evolution_menu.dm b/code/modules/antagonists/changeling/evolution_menu.dm index 1013712bc95..150ea34343e 100644 --- a/code/modules/antagonists/changeling/evolution_menu.dm +++ b/code/modules/antagonists/changeling/evolution_menu.dm @@ -88,6 +88,7 @@ return FALSE cling.give_power(new power_type) + SSblackbox.record_feedback("nested tally", "changeling_powers_purchased", 1, list("[initial(power.name)]")) return TRUE /datum/action/changeling/evolution_menu/proc/get_ability_tabs() diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index f3e98d67d27..56a88a97e76 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -36,6 +36,7 @@ RegisterSignal(user, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(retract), override = TRUE) RegisterSignal(user, COMSIG_MOB_WEAPON_APPEARS, PROC_REF(retract), override = TRUE) playsound(owner.loc, 'sound/effects/bone_break_1.ogg', 100, TRUE) + SSblackbox.record_feedback("nested tally", "changeling_powers", 1, list("[W.name]")) return W /datum/action/changeling/weapon/proc/retract(atom/target, any_hand = FALSE) diff --git a/code/modules/antagonists/changeling/powers/shriek.dm b/code/modules/antagonists/changeling/powers/shriek.dm index 7fd6c4ec3a0..5372ffb8c1c 100644 --- a/code/modules/antagonists/changeling/powers/shriek.dm +++ b/code/modules/antagonists/changeling/powers/shriek.dm @@ -54,6 +54,8 @@ L.on = TRUE L.break_light_tube() empulse(get_turf(user), 3, 5, 1) + + SSblackbox.record_feedback("nested tally", "changeling_powers", 1, list("[name]")) return TRUE /// A more expensive version, used during rounds with cyber rev station trait for balance reasons. diff --git a/code/modules/arcade/mob_hunt/battle_computer.dm b/code/modules/arcade/mob_hunt/battle_computer.dm deleted file mode 100644 index 228686fa951..00000000000 --- a/code/modules/arcade/mob_hunt/battle_computer.dm +++ /dev/null @@ -1,309 +0,0 @@ - -/obj/machinery/computer/mob_battle_terminal - name = "Nano-Mob Hunter GO! Battle Terminal" - desc = "Insert a mob card to partake in life-like Nano-Mob Battle Action!" - icon_state = "mob_battle_empty" - icon_screen = null - icon_keyboard = null - density = FALSE - anchored = TRUE - var/obj/item/nanomob_card/card - var/datum/mob_hunt/mob_info - var/obj/effect/landmark/battle_mob_point/avatar_point - var/obj/effect/nanomob/battle/avatar - var/ready = FALSE - var/team = "Grey" - -/obj/machinery/computer/mob_battle_terminal/red - pixel_y = 24 - dir = SOUTH - team = "Red" - -/obj/machinery/computer/mob_battle_terminal/blue - pixel_y = -24 - dir = NORTH - team = "Blue" - -/obj/machinery/computer/mob_battle_terminal/red/Initialize() - ..() - check_connection() - -/obj/machinery/computer/mob_battle_terminal/blue/Initialize() - ..() - check_connection() - -/obj/machinery/computer/mob_battle_terminal/update_icon_state() - if(card) - icon_state = "mob_battle_loaded" - else - icon_state = "mob_battle_empty" - -/obj/machinery/computer/mob_battle_terminal/Destroy() - eject_card(1) - if(SSmob_hunt) - if(SSmob_hunt.battle_turn) - SSmob_hunt.battle_turn = null - if(SSmob_hunt.red_terminal == src) - SSmob_hunt.red_terminal = null - if(SSmob_hunt.blue_terminal == src) - SSmob_hunt.blue_terminal = null - QDEL_NULL(avatar) - return ..() - -/obj/machinery/computer/mob_battle_terminal/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/nanomob_card)) - insert_card(O, user) - return - return ..() - -/obj/machinery/computer/mob_battle_terminal/proc/insert_card(obj/item/nanomob_card/new_card, mob/user) - if(!new_card) - return - if(card) - to_chat(user, "The card slot is currently filled.") - return - if(!new_card.mob_data) - to_chat(user, "This is a blank mob card.") - return - if(new_card.mob_data && !new_card.mob_data.cur_health) - to_chat(user, "This mob is incapacitated! Heal it before attempting to use it in battle!") - return - user.unEquip(new_card) - new_card.forceMove(src) - card = new_card - mob_info = card.mob_data - update_icon() - update_avatar() - updateUsrDialog() - -/obj/machinery/computer/mob_battle_terminal/proc/eject_card(override = 0) - if(!override) - if(ready && SSmob_hunt.battle_turn != team) - atom_say("You can't recall on your rival's turn!") - return - if(!card) - return - card.mob_data = mob_info - mob_info = null - card.forceMove(get_turf(src)) - card = null - update_avatar() - update_icon() - updateUsrDialog() - -/obj/machinery/computer/mob_battle_terminal/proc/update_avatar() - //if we don't have avatars yet, spawn them - if(!avatar) - if(!avatar_point) - log_debug("[src] attempted to spawn a battle mob avatar without a spawn point!") - return - else - avatar = new(get_turf(avatar_point)) - //update avatar info from card - if(mob_info) - avatar.mob_info = mob_info - else - avatar.mob_info = null - //tell the avatar to update themself with the new info - avatar.update_self() - -/obj/machinery/computer/mob_battle_terminal/attack_hand(mob/user) - add_fingerprint(user) - interact(user) - -/obj/machinery/computer/mob_battle_terminal/attack_ai(mob/user) - to_chat(user, "You cannot interface with this portion of the simulation.") - return - -/obj/machinery/computer/mob_battle_terminal/interact(mob/user) - check_connection() - var/datum/asset/mob_hunt_asset = get_asset_datum(/datum/asset/simple/mob_hunt) - mob_hunt_asset.send(user) - - var/dat = "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - if(ready && SSmob_hunt.battle_turn) //offer the surrender option if they are in a battle (ready), but don't have a card loaded - dat += "" - dat += "" - dat += "" - else - dat += "
" - dat += "[team] PLAYER" - dat += "
" - if(!card) - dat += "

No Nano-Mob card loaded.

" - dat += "
Surrender!
" - dat += "" - dat += "" - if(mob_info.nickname) - dat += "" - dat += "" - if(mob_info.nickname) - dat += "" - dat += "" - dat += "" - dat += "
" - dat += "

[mob_info.mob_name]

" - dat += "
" - else - dat += "" - var/img_src = SSassets.transport.get_asset_url("[mob_info.icon_state_normal].png") - if(mob_info.is_shiny) - dat += SSassets.transport.get_asset_url("[mob_info.icon_state_shiny].png") - dat += "" - dat += "
" - dat += "

[mob_info.nickname]

" - dat += "
" - dat += "
" - dat += "Health: [mob_info.cur_health] / [mob_info.max_health]
" - dat += "" - dat += "" - if(mob_info.cur_health) - dat += "" - else - dat += "" - dat += "" - dat += "" - dat += "
Attack!Incapacitated!Recall!
" - dat += "" - dat += "" - if(!ready) - dat += "" - dat += "Battle!" - dat += "" - if(ready && !SSmob_hunt.battle_turn) - dat += "" - dat += "Cancel Battle!" - dat += "" - dat += "" - - var/datum/browser/popup = new(user, "mob_battle_terminal", "Nano-Mob Hunter GO! Battle Terminal", 575, 400) - popup.set_content(dat) - popup.open() - -/obj/machinery/computer/mob_battle_terminal/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["attack"]) - do_attack() - - if(href_list["eject"]) - eject_card() - - if(href_list["surrender"]) - surrender() - - if(href_list["ready"]) - var/option = text2num(href_list["ready"]) - if(option == 1) - start_battle() - else if(option == 2) - ready = FALSE - atom_say("[team] Player cancels their battle challenge.") - - updateUsrDialog() - -/obj/machinery/computer/mob_battle_terminal/proc/check_connection() - if(team == "Red") - if(SSmob_hunt && !SSmob_hunt.red_terminal) - SSmob_hunt.red_terminal = src - else if(team == "Blue") - if(SSmob_hunt && !SSmob_hunt.blue_terminal) - SSmob_hunt.blue_terminal = src - - find_avatar_spawn_point() - -/obj/machinery/computer/mob_battle_terminal/proc/find_avatar_spawn_point() - if(avatar_point) - return - var/obj/effect/landmark/battle_mob_point/closest - for(var/obj/effect/landmark/battle_mob_point/bmp in GLOB.landmarks_list) - if(!istype(bmp, /obj/effect/landmark/battle_mob_point)) - continue - if(bmp.z != z) //only match with points on the same z-level) - continue - if(!closest || isnull(closest)) - closest = bmp - continue - if(closest == bmp) - continue - if((abs(x-bmp.x)+abs(y-bmp.y)) < (abs(x-closest.x)+abs(y-closest.y))) //get_dist would be preferable if it didn't count diagonals as 1 distance, so we have to rely on actual x/y distances in this janky way. - closest = bmp - if(closest) - avatar_point = closest - else - log_debug("[src] was unable to locate a nearby mob battle landmark! Unable to spawn battle avatars!") - -/obj/machinery/computer/mob_battle_terminal/proc/do_attack() - if(!ready) //no attacking if you arent ready to fight (duh) - return - if(!SSmob_hunt || team != SSmob_hunt.battle_turn) //don't attack unless it is actually our turn - return - else - var/message = "[mob_info.mob_name] attacks!" - if(mob_info.nickname) - message = "[mob_info.nickname] attacks!" - atom_say(message) - SSmob_hunt.launch_attack(team, mob_info.get_raw_damage(), mob_info.get_attack_type()) - -/obj/machinery/computer/mob_battle_terminal/proc/start_battle() - if(ready) //don't do anything if we are still ready - return - if(!card) //don't do anything if there isn't a card inserted - return - ready = TRUE - atom_say("[team] Player is ready for battle! Waiting for rival...") - SSmob_hunt.start_check() - -/obj/machinery/computer/mob_battle_terminal/proc/receive_attack(raw_damage, datum/mob_type/attack_type) - var/message = mob_info.take_damage(raw_damage, attack_type) - avatar.audible_message(message, null, 5) - if(!mob_info.cur_health) - SSmob_hunt.end_battle(team) - eject_card(1) //force the card out, they were defeated - else - SSmob_hunt.end_turn() - -/obj/machinery/computer/mob_battle_terminal/proc/surrender() - atom_say("[team] Player surrenders the battle!") - SSmob_hunt.end_battle(team, 1) - -////////////////////////////// -// Mob Healing Terminal // -// (Pokemon Center) // -////////////////////////////// - -/obj/machinery/computer/mob_healer_terminal - name = "Nano-Mob Hunter GO! Restoration Terminal" - desc = "Swipe a mob card to instantly restore it to full health!" - icon_state = "mob_battle_loaded" - icon_screen = null - icon_keyboard = null - density = FALSE - anchored = TRUE - dir = EAST - -/obj/machinery/computer/mob_healer_terminal/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/nanomob_card)) - heal_card(O, user) - return - return ..() - -/obj/machinery/computer/mob_healer_terminal/proc/heal_card(obj/item/nanomob_card/patient, mob/user) - if(!patient) - return - if(!patient.mob_data) - to_chat(user, "This is a blank mob card.") - return - if(patient.mob_data && patient.mob_data.cur_health == patient.mob_data.max_health) - to_chat(user, "This mob is already at maximum health!") - return - patient.mob_data.cur_health = patient.mob_data.max_health - to_chat(user, "[patient.mob_data.nickname ? patient.mob_data.nickname : patient.mob_data.mob_name] has been restored to full health!") diff --git a/code/modules/arcade/mob_hunt/mob_avatar.dm b/code/modules/arcade/mob_hunt/mob_avatar.dm deleted file mode 100644 index ecab58523db..00000000000 --- a/code/modules/arcade/mob_hunt/mob_avatar.dm +++ /dev/null @@ -1,168 +0,0 @@ -/obj/effect/nanomob - name = "Nano-Mob Avatar" //will be overridden by the mob datum name value when created - desc = "A wild Nano-Mob appeared! Hit it with your PDA with the game open to attempt to capture it!" - invisibility = 101 - alpha = 128 - anchored = TRUE //just in case - density = FALSE - icon = 'icons/effects/mob_hunt.dmi' - var/state_name - var/datum/mob_hunt/mob_info = null - var/list/clients_encountered = list() //tracks who has already interacted with us, so they can't attempt a second capture - var/image/avatar - -/obj/effect/nanomob/Initialize(mapload, datum/mob_hunt/new_info) - . = ..() - if(!new_info) - return INITIALIZE_HINT_QDEL - mob_info = new_info - RegisterSignal(mob_info, COMSIG_PARENT_QDELETING, PROC_REF(delete_wrapper)) - update_self() - forceMove(mob_info.spawn_point) - if(!mob_info.is_trap) - addtimer(CALLBACK(src, PROC_REF(despawn)), mob_info.lifetime) - -/obj/effect/nanomob/Destroy() - SSmob_hunt.trap_spawns -= src - SSmob_hunt.normal_spawns -= src - mob_info = null // Can't delete this since multiple players can get the exact same /datum/mob_hunt. (This should be refactored) - clients_encountered.Cut() - QDEL_NULL(avatar) - return ..() - -/obj/effect/nanomob/proc/delete_wrapper() - SIGNAL_HANDLER - qdel(src) - -/obj/effect/nanomob/proc/update_self() - if(!mob_info) - return - name = mob_info.mob_name - desc = "A wild [name] (level [mob_info.level]) appeared! Hit it with your PDA with the game open to attempt to capture it!" - if(mob_info.is_shiny) - state_name = mob_info.icon_state_shiny - else - state_name = mob_info.icon_state_normal - avatar = image(icon, src, state_name) - avatar.override = 1 - add_alt_appearance("nanomob_avatar", avatar) - -/obj/effect/nanomob/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/pda)) - var/obj/item/pda/P = O - attempt_capture(P, -20) //attempting a melee capture reduces the mob's effective run_chance by 20% to balance the risk of triggering a trap mob - return 1 - -/obj/effect/nanomob/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - if(istype(AM, /obj/item/pda)) - var/obj/item/pda/P = AM - attempt_capture(P) //attempting a ranged capture does not affect the mob's effective run_chance but does prevent you from being shocked by a trap mob - return 1 - -/obj/effect/nanomob/proc/attempt_capture(obj/item/pda/P, catch_mod = 0) //negative catch_mods lower effective run chance, - if(!P || !P.current_app || !istype(P.current_app, /datum/data/pda/app/mob_hunter_game) || !P.cartridge) - return - - var/datum/data/pda/app/mob_hunter_game/client = P.current_app - var/total_catch_mod = client.catch_mod + catch_mod //negative values decrease the chance of the mob running, positive values makes it more likely to flee - if(!client.connected) //must be connected to attempt captures - P.atom_say("No server connection. Capture aborted.") - return - - if(mob_info.is_trap) //traps work even if you ran into them before, which is why this is before the clients_encountered check - if(client.hacked) //hacked copies of the game (copies capable of setting traps) are protected from traps - return - if(iscarbon(P.loc)) - var/mob/living/carbon/C = P.loc - //Strike them down with a lightning bolt to complete the illusion (copied from the surge reagent overdose, probably could make this a general-use proc in the future) - playsound(get_turf(C), 'sound/effects/eleczap.ogg', 75, 1) - var/icon/I=new('icons/obj/zap.dmi',"lightningend") - I.Turn(-135) - var/obj/effect/overlay/beam/B = new(get_turf(C)) - B.pixel_x = rand(-20, 0) - B.pixel_y = rand(-20, 0) - B.icon = I - //then actually do the damage/stun - C.electrocute_act(20, P, 1) //same damage as a revenant's overload ability, except subject to gloves/species shock resistance (for human mobs at least) - return - - if(client in clients_encountered) //we've already dealt with you, go away! - return - else //deal with the new hunter by either running away or getting caught - clients_encountered += client - var/message = null - var/effective_run_chance = mob_info.run_chance + total_catch_mod - if((effective_run_chance > 0) && prob(effective_run_chance)) - message += "Capture failed! [name] escaped [P.owner ? "from [P.owner]" : "from this hunter"]!" - conceal(client) - else - if(client.register_capture(mob_info, 1)) - message += "Capture success! [P.owner ? P.owner : "This hunter"] captured [name]!" - conceal(client) - else - message += "Capture error! Try again." - clients_encountered -= client //if the capture registration failed somehow, let them have another chance with this mob - P.atom_say(message) - -/obj/effect/nanomob/proc/despawn() - if(SSmob_hunt) - if(mob_info.is_trap) - SSmob_hunt.trap_spawns -= src - else - SSmob_hunt.normal_spawns -= src - qdel(src) - -/obj/effect/nanomob/proc/reveal() - if(!SSmob_hunt) - return - var/list/show_to = list() - for(var/A in SSmob_hunt.connected_clients) - if((A in clients_encountered) || !SSmob_hunt.connected_clients[A]) - continue - show_to |= SSmob_hunt.connected_clients[A] - display_alt_appearance("nanomob_avatar", show_to) - -/obj/effect/nanomob/proc/conceal(list/hide_from) - if(!SSmob_hunt) - return - var/list/hiding_from = list() - if(hide_from) - hiding_from = hide_from - else - for(var/A in SSmob_hunt.connected_clients) - if((A in clients_encountered) && SSmob_hunt.connected_clients[A]) - hiding_from |= SSmob_hunt.connected_clients[A] - hide_alt_appearance("nanomob_avatar", hiding_from) - -// BATTLE MOB AVATARS - -/obj/effect/nanomob/battle - name = "Nano-Mob Battle Avatar" - desc = "A new challenger approaches!" - invisibility = 0 - icon_state = "placeholder" - var/obj/machinery/computer/mob_battle_terminal/my_terminal - -/obj/effect/nanomob/battle/update_self() - if(!mob_info) - name = "Nano-Mob Battle Avatar" - desc = "A new challenger approaches" - icon_state = "placeholder" - else - name = mob_info.mob_name - desc = "A tamed [name] (level [mob_info.level]) ready for battle!" - if(mob_info.is_shiny) - icon_state = mob_info.icon_state_shiny - else - icon_state = mob_info.icon_state_normal - -/obj/effect/nanomob/battle/attempt_capture(obj/item/pda/P, catch_mod = 0) - //you can't capture battle avatars, since they belong to someone already - return - -//battle avatars are always visible, so we can ignore reveal and conceal calls for them -/obj/effect/nanomob/battle/reveal() - return - -/obj/effect/nanomob/battle/conceal() - return diff --git a/code/modules/arcade/mob_hunt/mob_cards.dm b/code/modules/arcade/mob_hunt/mob_cards.dm deleted file mode 100644 index 6acfe826f44..00000000000 --- a/code/modules/arcade/mob_hunt/mob_cards.dm +++ /dev/null @@ -1,43 +0,0 @@ - -//Standard Cards -/obj/item/nanomob_card - name = "Nano-Mob Hunter Trading Card" - desc = "A blank Nano-Mob Hunter Trading Card. Worthless!" - icon = 'icons/obj/card.dmi' - icon_state = "trade_card" - force = 0 - throwforce = 1 - w_class = WEIGHT_CLASS_TINY - var/datum/mob_hunt/mob_data - -/obj/item/nanomob_card/proc/update_info() - if(!mob_data) - return - if(mob_data.is_shiny) - name = "Holographic [mob_data.mob_name] Nano-Mob Hunter Card" - desc = "WOW! A holographic trading card containing a level [mob_data.level] [mob_data.mob_name]!" - icon_state = "trade_card_holo" - else - name = "[mob_data.mob_name] Nano-Mob Hunter Card" - desc = "A trading card containing a level [mob_data.level] [mob_data.mob_name]!" - -//Booster Pack Cards (random mob data) -/obj/item/nanomob_card/booster - name = "Nano-Mob Hunter Booster Pack Card" - desc = "A random Nano-Mob Trading Card from a Booster Pack. Wonder what it is?" - -/obj/item/nanomob_card/booster/New() - ..() - var/datum/mob_hunt/mob_info = pick(subtypesof(/datum/mob_hunt)) - mob_data = new mob_info(0,null,1) - update_info() - -//Booster Packs (Box of booster pack cards) -/obj/item/storage/box/nanomob_booster_pack - name = "Nano-Mob Hunter Trading Card Booster Pack" - desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" - can_hold = list(/obj/item/nanomob_card) - -/obj/item/storage/box/nanomob_booster_pack/populate_contents() - for(var/i in 1 to 6) - new /obj/item/nanomob_card/booster(src) diff --git a/code/modules/arcade/mob_hunt/mob_datums.dm b/code/modules/arcade/mob_hunt/mob_datums.dm deleted file mode 100644 index fc60e17bbbe..00000000000 --- a/code/modules/arcade/mob_hunt/mob_datums.dm +++ /dev/null @@ -1,480 +0,0 @@ - -/datum/mob_hunt - //GENERAL STATS AND VARIABLES - var/mob_name = "Generic Mob" //the mob's original name (its species/type/whatever) - var/nickname = "" //the mob's nickname (if given by the owner) - var/run_chance = 0 //percent chance the mob will escape capture attempts (higher is obviously more likely to get away) - - //COMBAT STATS AND VARIABLES - var/level = 0 //actual level of this mob (don't set this, it gets overwritten in New()) - var/min_level = 1 //minimum level of this mob (used for randomizing the actual level) - var/max_level = 1 //maximum level of this mob (used for randomizing the actual level) - var/exp = 0 //number of battles the mob has won towards the next level (resets to 0 on level-up) - var/exp_to_level = 3 //number of battles the mob must win to level up (in case we want to make some mobs harder or easier to level) - //the types of the mob will be used for battles to determine damage resistance or weakness (mob_type_datums.dm) - var/datum/mob_type/primary_type //Make sure you set this or the mob will be unable to deal damage and will take absurd damage in battles - var/datum/mob_type/secondary_type //Don't set if not a dual-type mob so the mob will only calculate damage based on primary type - var/base_attack = 5 //base damage dealt by the mob's attacks for battling (effectively damage dealt at level 0) - var/base_health = 5 //base health of the mob for battling (effectively max health at level 0) - var/attack_multiplier = 1 //how much additional damage per level the mob deals (level * attack_multiplier) - var/health_multiplier = 1 //how much additional health per level the mob gets (level * health_multiplier) for calculating max health - var/cur_health = 0 - var/max_health = 0 - - //SPAWN PREFERENCES AND VARIABLES - //A note on mob spawn preferences: The mob types also have preferences, which are handled prior to per-mob preferences, so ultimately you use a combined set of preferences - var/list/area_blacklist = list() //list of areas this mob can NOT spawn in (such as the bridge) - var/list/turf_blacklist = list() //list of turfs this mob can NOT spawn on (such as wood floors) - var/list/area_whitelist = list() //list of areas this mob is more likely to spawn in (can be used to reinclude subtypes of blacklisted areas) - var/list/turf_whitelist = list() //list of turfs this mob is more likely to spawn on (can be used to reinclude subtypes of blacklisted turfs) - var/turf/spawn_point //gets set and sent to the game server to spawn its avatar (generated in select_spawn or assigned via set_trap) - var/lifetime = 6000 //number of deciseconds the mob will remain before despawning (REMEMBER: DECISECONDS! So 6000 is 600 seconds which is 10 minutes) - var/is_shiny = 0 //if this gets set at spawn (super rare), the mob is considered "shiny" and will use the shiny icon_state and holographic cards - - //the icon file for mob_hunt stuff is 'icons/effects/mob_hunt.dmi' so reference that for the following vars - var/icon_state_normal = "placeholder" //the icon_state for this mob's normal version - var/icon_state_shiny = "placeholder" //the icon_state for this mob's rare shiney version - - var/is_trap = 0 //if this gets set, the mob is a booby-trap and will electrocute any players that dare attempt to catch it - -/datum/mob_hunt/New(set_trap = 0, turf/trap_turf = null, no_register = 0) - if(set_trap) - level = max_level - is_trap = 1 - spawn_point = trap_turf - else - level = rand(min_level, max_level) - if(prob(1) && prob(1)) - is_shiny = 1 - max_health = base_health + (level * health_multiplier) - cur_health = max_health - if(primary_type) - primary_type = new primary_type() - if(secondary_type) - secondary_type = new secondary_type() - if(no_register) //for booster pack cards - return - if(SSmob_hunt) - if(set_trap) - if(SSmob_hunt.register_trap(src)) - return - else if(select_spawn()) - if(SSmob_hunt.register_spawn(src)) - return - qdel(src) //if you reach this, the datum is just pure clutter, so delete it - -/datum/mob_hunt/proc/select_spawn() - var/list/possible_areas = get_possible_areas() - if(!length(possible_areas)) - log_admin("No possible areas to spawn [type] found. Possible code/mapping error?") - return 0 - while(length(possible_areas)) - //randomly select an area from our possible_areas list to try spawning in, then remove it from possible_areas so it won't get picked over and over forever. - var/spawn_area_path = pickweight(possible_areas) - var/area/spawn_area = locate(spawn_area_path) - possible_areas -= spawn_area_path - if(!spawn_area) - break - //clear and generate a fresh list of turfs in the selected area, weighted based on white/black lists - var/list/possible_turfs = get_possible_turfs(spawn_area) - if(!length(possible_turfs)) //If we don't have any possible turfs, this attempt was a failure. Try again. - continue - //if we got this far, we're spawning on this attempt, hooray! - spawn_point = pickweight(possible_turfs) - break - if(!spawn_point) - //if we get to this, we failed every attempt to find a suitable turf for EVERY area in our list of possible areas. DAMN. - log_admin("No acceptable turfs to spawn [type] on could be located. Possible code/mapping error, or someone replaced/destroyed all the acceptable turf types?") - return 0 - return 1 - -/datum/mob_hunt/proc/get_possible_areas() - var/list/possible_areas = list() - //setup, sets all station areas (and subtypes) to weight 1 - for(var/area/A in SSmapping.existing_station_areas) - if(istype(A, /area/holodeck)) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on CC level as well - continue - if(A in possible_areas) - continue - for(var/areapath in typesof(A)) - possible_areas[areapath] = 1 - //primary type preferences - if(primary_type) - for(var/A in primary_type.area_whitelist) - for(var/areapath in typesof(A)) - possible_areas[areapath] += 4 - for(var/A in primary_type.area_blacklist) - for(var/areapath in typesof(A)) - possible_areas[areapath] -= 2 - //secondary type preferences - if(secondary_type) - for(var/A in secondary_type.area_whitelist) - for(var/areapath in typesof(A)) - possible_areas[areapath] += 4 - for(var/A in secondary_type.area_blacklist) - for(var/areapath in typesof(A)) - possible_areas[areapath] -= 2 - //mob preferences - for(var/A in area_whitelist) - for(var/areapath in typesof(A)) - possible_areas[areapath] += 4 - for(var/A in area_blacklist) - for(var/areapath in typesof(A)) - possible_areas[areapath] -= 2 - //weight check, remove negative or zero weight areas from the list, then return the list. - for(var/areapath in possible_areas) - //remove any areas that shouldn't be on the station-level - if(possible_areas[areapath] < 1) - possible_areas -= areapath - continue - return possible_areas - -/datum/mob_hunt/proc/get_possible_turfs(area/spawn_area) - if(!spawn_area) - return list() - var/list/possible_turfs = list() - //setup, sets all turfs in spawn_area to weight 1 - for(var/turf/T in spawn_area) - if(!is_station_level(T.z)) //mobs will only consider station-level turfs for spawning. Largely here so we won't have to worry about mapping errors or mobs on the derelict solars - continue - possible_turfs[T] = 1 - //primary type preferences - if(primary_type) - if(is_type_in_list(T, primary_type.turf_whitelist)) - possible_turfs[T] += 4 - if(is_type_in_list(T, primary_type.turf_blacklist)) - possible_turfs[T] -= 2 - //secondary type preferences - if(secondary_type) - if(is_type_in_list(T, secondary_type.turf_whitelist)) - possible_turfs[T] += 4 - if(is_type_in_list(T, secondary_type.turf_blacklist)) - possible_turfs[T] -= 2 - //mob preferences - if(is_type_in_list(T, turf_whitelist)) - possible_turfs[T] += 4 - if(is_type_in_list(T, turf_blacklist)) - possible_turfs[T] -= 2 - //weight check, remove negative or zero weight turfs from the list, then return the list - if(possible_turfs[T] < 1) - possible_turfs -= T - return possible_turfs - -/datum/mob_hunt/proc/calc_def_multiplier(datum/mob_type/attack_type) - if(!primary_type) - return 99 //typeless mobs are weak to everything since they shouldn't exist - if(!attack_type) //typeless attacks will return a multiplier of 1 in case we want to use this for calculating unmodified damage for some reason (UI maybe?) - return 1 - - var/multiplier = 1 - if(attack_type in primary_type.immunity) - return 0 //a single immunity negates all damage - else if(attack_type in primary_type.resistance) - multiplier *= 0.5 - else if(attack_type in primary_type.weakness) - multiplier *= 2 - else - multiplier *= 1 - - if(!secondary_type) //if we don't have a second type, we're done here - return multiplier - if(attack_type in secondary_type.immunity) - return 0 //a single immunity negates all damage - else if(attack_type in secondary_type.resistance) - multiplier *= 0.5 - else if(attack_type in secondary_type.weakness) - multiplier *= 2 - else - multiplier *= 1 - return multiplier - -/datum/mob_hunt/proc/take_damage(raw_damage, datum/mob_type/attack_type) - var/message = "" - var/multiplier = calc_def_multiplier(attack_type) - var/total_damage = raw_damage * multiplier - if(!cur_health) //it's already downed, quit hitting it - return null - if(!total_damage) - message += "The attack is completely ineffective! " - else - cur_health = max(cur_health - total_damage, 0) - switch(multiplier) - if(0) - message += "The attack is completely ineffective! " - if(0.25) - message += "It's barely effective... " - if(0.5) - message += "It's not very effective... " - if(2) - message += "It's super effective! " - if(4) - message += "It's ultra effective! " - if(99) - message += pick("REKT! ", "DUNKED! ", "DEFENSE BREAK! ", "WOMBO-COMBO'D!") - if(!cur_health) - message += "[nickname ? nickname : mob_name] is downed!" - return message - -/datum/mob_hunt/proc/get_raw_damage() - return (level * attack_multiplier) - -/datum/mob_hunt/proc/get_attack_type() - var/datum/mob_type/attack_type = primary_type - if(secondary_type && prob(40)) - attack_type = secondary_type - return attack_type - -/datum/mob_hunt/proc/gain_exp() - exp++ - var/message = "[nickname ? nickname : mob_name] gained EXP! ([exp] / [exp_to_level] EXP)" - if(exp >= exp_to_level) - message = levelup() - return message - -/datum/mob_hunt/proc/levelup() - var/message = "" - level++ - exp = 0 - if(level > max_level) //This is where we would trigger an evolution, when those are added (need to add evolved forms first) - level = max_level //for now though, we'll just cap them back at their max_level - message += "[nickname ? nickname : mob_name] can't get any stronger right now!" - else - max_health = base_health + (level * health_multiplier) - cur_health = max_health //full heal on level-up - message += "[nickname ? nickname : mob_name] has reached level [level]!" - return message - -/datum/mob_hunt/proc/get_type1() - if(!primary_type) - return "Typeless" - else - return primary_type.name - -/datum/mob_hunt/proc/get_type2() - if(!secondary_type) - return null - else - return secondary_type.name - - -/datum/mob_hunt/nemabug - mob_name = "Nemabug" - run_chance = 50 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_BUG - icon_state_normal = "nemabug" - icon_state_shiny = "nemabug_shiny" - lifetime = 6000 - -/datum/mob_hunt/stoutquill - mob_name = "Stoutquill" - run_chance = 50 - min_level = 5 - max_level = 15 - primary_type = NANOMOB_TYPE_ICE - icon_state_normal = "stoutquill" - icon_state_shiny = "stoutquill_shiny" - lifetime = 4500 - -/datum/mob_hunt/spectra - mob_name = "Spectra" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_POISON - icon_state_normal = "spectra" - icon_state_shiny = "spectra_shiny" - lifetime = 6000 - -/datum/mob_hunt/dunny - mob_name = "Dunny" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_FIRE - icon_state_normal = "dunny" - icon_state_shiny = "dunny_shiny" - lifetime = 6000 - -/datum/mob_hunt/buffsel - mob_name = "Buffsel" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_ROCK - icon_state_normal = "buffsel" - icon_state_shiny = "buffsel_shiny" - lifetime = 6000 - -/datum/mob_hunt/quarrel - mob_name = "Quarrel" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_NORMAL - icon_state_normal = "quarrel" - icon_state_shiny = "quarrel_shiny" - lifetime = 6000 - -/datum/mob_hunt/vulerrt - mob_name = "Vulerrt" - run_chance = 50 - min_level = 5 - max_level = 15 - primary_type = NANOMOB_TYPE_DARK - icon_state_normal = "vulerrt" - icon_state_shiny = "vulerrt_shiny" - turf_whitelist = list() - lifetime = 4500 - -/datum/mob_hunt/strudel - mob_name = "Strudel" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_ELECTRIC - icon_state_normal = "strudel" - icon_state_shiny = "strudel_shiny" - lifetime = 4500 - -/datum/mob_hunt/folstick - mob_name = "Folstick" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_WATER - icon_state_normal = "folstick" - icon_state_shiny = "folstick_shiny" - lifetime = 6000 - -/datum/mob_hunt/glimmerflare - mob_name = "Glimmerflare" - run_chance = 50 - min_level = 5 - max_level = 15 - primary_type = NANOMOB_TYPE_PSYCHIC - icon_state_normal = "glimmerflare" - icon_state_shiny = "glimmerflare_shiny" - lifetime = 4500 - -/datum/mob_hunt/leecoon - mob_name = "Leecoon" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_GRASS - icon_state_normal = "leecoon" - icon_state_shiny = "leecoon_shiny" - lifetime = 6000 - -/datum/mob_hunt/halk - mob_name = "Halk" - run_chance = 35 - min_level = 1 - max_level = 10 - primary_type = NANOMOB_TYPE_FLYING - icon_state_normal = "halk" - icon_state_shiny = "halk_shiny" - lifetime = 6000 - -/datum/mob_hunt/gooby - mob_name = "Gooby" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_ELECTRIC - secondary_type = NANOMOB_TYPE_BUG - icon_state_normal = "gooby" - icon_state_shiny = "gooby_shiny" - lifetime = 3000 - -/datum/mob_hunt/pandoom - mob_name = "Pandoom" - run_chance = 50 - min_level = 5 - max_level = 15 - primary_type = NANOMOB_TYPE_GHOST - icon_state_normal = "pandoom" - icon_state_shiny = "pandoom_shiny" - lifetime = 4500 - -/datum/mob_hunt/relish - mob_name = "Relish" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_FIRE - secondary_type = NANOMOB_TYPE_GROUND - icon_state_normal = "relish" - icon_state_shiny = "relish_shiny" - lifetime = 3000 - -/datum/mob_hunt/xofine - mob_name = "Xofine" - run_chance = 50 - min_level = 5 - max_level = 10 - primary_type = NANOMOB_TYPE_FIRE - secondary_type = NANOMOB_TYPE_NORMAL - icon_state_normal = "xofine" - icon_state_shiny = "xofine_shiny" - lifetime = 3000 - -/datum/mob_hunt/gitten - mob_name = "Gitten" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_WATER - secondary_type = NANOMOB_TYPE_POISON - icon_state_normal = "gitten" - icon_state_shiny = "gitten_shiny" - lifetime = 3000 - -/datum/mob_hunt/nai - mob_name = "Nai" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_GRASS - secondary_type = NANOMOB_TYPE_NORMAL - icon_state_normal = "nai" - icon_state_shiny = "nai_shiny" - lifetime = 3000 - -/datum/mob_hunt/pyroghast - mob_name = "Pyroghast" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_FIRE - secondary_type = NANOMOB_TYPE_GHOST - icon_state_normal = "pyroghast" - icon_state_shiny = "pyroghast" - lifetime = 4500 - -/datum/mob_hunt/starslam - mob_name = "Starslam" - run_chance = 65 - min_level = 5 - max_level = 20 - primary_type = NANOMOB_TYPE_FIGHTING - secondary_type = NANOMOB_TYPE_ICE - icon_state_normal = "starslam" - icon_state_shiny = "starslam_shiny" - lifetime = 2500 - -/datum/mob_hunt/pheron - mob_name = "Pheron" - run_chance = 85 - min_level = 10 - max_level = 20 - primary_type = NANOMOB_TYPE_BLUESPACE - icon_state_normal = "pheron" - icon_state_shiny = "pheron_shiny" - area_blacklist = list() - turf_blacklist = list() - area_whitelist = list() - turf_whitelist = list() - lifetime = 2000 diff --git a/code/modules/arcade/mob_hunt/mob_type_datums.dm b/code/modules/arcade/mob_hunt/mob_type_datums.dm deleted file mode 100644 index 1789ac67912..00000000000 --- a/code/modules/arcade/mob_hunt/mob_type_datums.dm +++ /dev/null @@ -1,241 +0,0 @@ - -/datum/mob_type - var/name = "Typeless" - var/list/weakness = list() - var/list/resistance = list() - var/list/immunity = list() - - //Type-based spawn preferences (to eliminate copy-pasting the same area and turf lists on each mob type) - var/list/area_blacklist = list() //areas to be avoided - var/list/area_whitelist = list() //areas to be more preferred - var/list/turf_blacklist = list() //turf types to be avoided - var/list/turf_whitelist = list() //turf types to be more preferred - -//Type defines, to avoid spelling mistakes -/datum/mob_type/fire - name = "Fire" - weakness = list(NANOMOB_TYPE_WATER, - NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_GROUND) - resistance = list(NANOMOB_TYPE_BUG, - NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_ICE, - NANOMOB_TYPE_STEEL) - area_blacklist = list(/area/station/public/toilet, - /area/station/science/server/coldroom) - area_whitelist = list(/area/station/maintenance/turbine, - /area/station/maintenance/incinerator, - /area/station/service/kitchen) - turf_blacklist = list(/turf/simulated/floor/beach/water) - -/datum/mob_type/water - name = "Water" - weakness = list(NANOMOB_TYPE_ELECTRIC, - NANOMOB_TYPE_GRASS) - resistance = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_ICE, - NANOMOB_TYPE_STEEL, - NANOMOB_TYPE_WATER) - area_blacklist = list(/area/station/maintenance/turbine, - /area/station/maintenance/incinerator, - /area/station/service/kitchen) - area_whitelist = list(/area/station/public/toilet) - turf_whitelist = list(/turf/simulated/floor/beach/water) - -/datum/mob_type/grass - name = "Grass" - weakness = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_BUG, - NANOMOB_TYPE_POISON, - NANOMOB_TYPE_ICE, - NANOMOB_TYPE_FLYING) - resistance = list(NANOMOB_TYPE_WATER, - NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_ELECTRIC, - NANOMOB_TYPE_GROUND) - area_blacklist = list(/area/station/science) - area_whitelist = list(/area/station/service/hydroponics, - /area/station/public/construction) // dont ask me why grass types can appear in construction sites, I'm just migrating areas - turf_whitelist = list(/turf/simulated/floor/grass) - -/datum/mob_type/electric - name = "Electric" - weakness = list(NANOMOB_TYPE_GROUND) - resistance = list(NANOMOB_TYPE_ELECTRIC, - NANOMOB_TYPE_FLYING, - NANOMOB_TYPE_STEEL) - area_whitelist = list(/area/station/engineering/engine, - /area/station/science/server, - /area/station/maintenance, - /area/station/turret_protected/ai, - /area/station/turret_protected/ai_upload, - /area/station/turret_protected/aisat/interior, - /area/station/aisat, - /area/station/science/robotics) - turf_whitelist = list(/turf/simulated/floor/bluegrid) - -/datum/mob_type/ground - name = "Ground" - weakness = list(NANOMOB_TYPE_WATER, - NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_ICE) - resistance = list(NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_POISON) - immunity = list(NANOMOB_TYPE_ELECTRIC) - -/datum/mob_type/rock - name = "Rock" - weakness = list(NANOMOB_TYPE_WATER, - NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_GROUND, - NANOMOB_TYPE_FIGHTING, - NANOMOB_TYPE_STEEL) - resistance = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_FLYING, - NANOMOB_TYPE_POISON, - NANOMOB_TYPE_NORMAL) - area_whitelist = list(/area/station/supply, - /area/station/maintenance/disposal) - turf_whitelist = list(/turf/simulated/wall, - /turf/simulated/floor/mineral) - -/datum/mob_type/bug - name = "Bug" - weakness = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_FLYING) - resistance = list(NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_GROUND, - NANOMOB_TYPE_FIGHTING) - area_blacklist = list(/area/station/science) - area_whitelist = list(/area/station/service/hydroponics, - /area/station/public/construction) // dont ask me why bug types can appear in construction sites, I'm just migrating areas - turf_whitelist = list(/turf/simulated/floor/grass) - -/datum/mob_type/poison - name = "Poison" - weakness = list(NANOMOB_TYPE_GROUND, - NANOMOB_TYPE_PSYCHIC) - resistance = list(NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_BUG, - NANOMOB_TYPE_POISON, - NANOMOB_TYPE_FIGHTING) - area_blacklist = list(/area/station/medical, - /area/station/service/janitor) - area_whitelist = list(/area/station/medical/virology, - /area/station/science, - /area/station/command/office/rd, - /area/station/maintenance/asmaint2) - -/datum/mob_type/normal - name = "Normal" - weakness = list(NANOMOB_TYPE_FIGHTING) - immunity = list(NANOMOB_TYPE_GHOST) - -/datum/mob_type/fighting - name = "Fighting" - weakness = list(NANOMOB_TYPE_PSYCHIC, - NANOMOB_TYPE_FLYING) - resistance = list(NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_BUG, - NANOMOB_TYPE_DARK) - area_blacklist = list(/area/station/medical) - area_whitelist = list(/area/station/service/bar, - /area/station/public/fitness, - /area/station/security) - turf_whitelist = list(/turf/simulated/floor/wood) - -/datum/mob_type/psychic - name = "Psychic" - weakness = list(NANOMOB_TYPE_BUG, - NANOMOB_TYPE_GHOST, - NANOMOB_TYPE_DARK) - resistance = list(NANOMOB_TYPE_FIGHTING, - NANOMOB_TYPE_PSYCHIC) - area_blacklist = list(/area/station/science, - /area/station/command/office/rd, - /area/station/maintenance/asmaint2, - /area/station/command/teleporter, - /area/station/command/gateway) - area_whitelist = list(/area/station/service/library, - /area/station/service/chapel, - /area/station/medical/psych) - -/datum/mob_type/ghost - name = "Ghost" - weakness = list(NANOMOB_TYPE_GHOST, - NANOMOB_TYPE_DARK) - resistance = list(NANOMOB_TYPE_BUG, - NANOMOB_TYPE_POISON) - immunity = list(NANOMOB_TYPE_NORMAL, - NANOMOB_TYPE_FIGHTING) - area_whitelist = list(/area/station/medical/morgue, - /area/station/service/chapel, - /area/station/medical/cloning) - -/datum/mob_type/ice - name = "Ice" - weakness = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_FIGHTING, - NANOMOB_TYPE_STEEL) - resistance = list(NANOMOB_TYPE_ICE) - area_blacklist = list(/area/station/maintenance/turbine, - /area/station/maintenance/incinerator, - /area/station/service/kitchen) - area_whitelist = list(/area/station/science/server/coldroom) - -/datum/mob_type/flying - name = "Flying" - weakness = list(NANOMOB_TYPE_ELECTRIC, - NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_ICE) - resistance = list(NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_BUG, - NANOMOB_TYPE_FIGHTING) - immunity = list(NANOMOB_TYPE_GROUND) - area_blacklist = list(/area/station/maintenance) - area_whitelist = list(/area/station/hallway) - -/datum/mob_type/bluespace - name = "Bluespace" - weakness = list(NANOMOB_TYPE_ICE, - NANOMOB_TYPE_BLUESPACE) - resistance = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_WATER, - NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_ELECTRIC) - -/datum/mob_type/dark - name = "Dark" - weakness = list(NANOMOB_TYPE_BUG, - NANOMOB_TYPE_FIGHTING) - resistance = list(NANOMOB_TYPE_GHOST, - NANOMOB_TYPE_DARK) - immunity = list(NANOMOB_TYPE_PSYCHIC) - area_blacklist = list(/area/station/engineering/solar, - /area/station/maintenance/auxsolarport, - /area/station/maintenance/starboardsolar, - /area/station/maintenance/portsolar, - /area/station/maintenance/auxsolarstarboard, - /area/station/service/clown) - area_whitelist = list(/area/station/maintenance, - /area/station/service/mime) - turf_blacklist = list(/turf/simulated/floor/light) - -/datum/mob_type/steel - name = "Steel" - weakness = list(NANOMOB_TYPE_FIRE, - NANOMOB_TYPE_GROUND, - NANOMOB_TYPE_FIGHTING) - resistance = list(NANOMOB_TYPE_GRASS, - NANOMOB_TYPE_ROCK, - NANOMOB_TYPE_BUG, - NANOMOB_TYPE_NORMAL, - NANOMOB_TYPE_PSYCHIC, - NANOMOB_TYPE_ICE, - NANOMOB_TYPE_FLYING, - NANOMOB_TYPE_BLUESPACE, - NANOMOB_TYPE_STEEL) - immunity = list(NANOMOB_TYPE_POISON) diff --git a/code/modules/arcade/prize_datums.dm b/code/modules/arcade/prize_datums.dm index 40d8f4d54e3..7e9481bceee 100644 --- a/code/modules/arcade/prize_datums.dm +++ b/code/modules/arcade/prize_datums.dm @@ -275,12 +275,6 @@ GLOBAL_DATUM_INIT(global_prizes, /datum/prizes, new()) typepath = /obj/item/clothing/under/syndicate/tacticool cost = 90 -/datum/prize_item/nanomob_booster - name = "Nano-Mob Hunter Trading Card Booster Pack" - desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" - typepath = /obj/item/storage/box/nanomob_booster_pack - cost = 100 - /datum/prize_item/fakespell name = "Fake Spellbook" desc = "Perform magic! Astound your friends! Get mistaken for an enemy of the corporation!" diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index f3315c480e4..2a293d76324 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -227,6 +227,9 @@ /obj/effect/beam/i_beam/update_icon_state() transform = turn(matrix(), dir2angle(dir)) +/obj/effect/beam/i_beam/Process_Spacemove(movement_dir) + return TRUE + /obj/effect/beam/i_beam/process() life_cycles++ if(loc.density || !master || life_cycles >= life_cap) diff --git a/code/modules/asset_cache/assets/asset_mob_hunt.dm b/code/modules/asset_cache/assets/asset_mob_hunt.dm deleted file mode 100644 index ed1f7494e33..00000000000 --- a/code/modules/asset_cache/assets/asset_mob_hunt.dm +++ /dev/null @@ -1,7 +0,0 @@ -/datum/asset/simple/mob_hunt/register() - for(var/state in icon_states('icons/effects/mob_hunt.dmi')) - if(state == "Placeholder") - continue - assets["[state].png"] = icon('icons/effects/mob_hunt.dmi', state) - - return ..() diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index c3706032100..82cd7383c15 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -198,8 +198,6 @@ if(our_excited_group) last_share_check() -#define LAVALAND_TEMPERATURE 500 - if(planetary_atmos) //share our air with the "atmosphere" "above" the turf var/datum/gas_mixture/G = new G.oxygen = oxygen @@ -208,7 +206,7 @@ G.toxins = toxins G.sleeping_agent = sleeping_agent G.agent_b = agent_b - G.temperature = LAVALAND_TEMPERATURE // Temperature is modified at runtime; we only care about the turf's initial temperature + G.temperature = initial(temperature) // Temperature is modified at runtime; we only care about the turf's initial temperature G.archive() if(!air.compare(G)) if(!our_excited_group) @@ -218,8 +216,6 @@ air.share(G, adjacent_turfs_length) last_share_check() -#undef LAVALAND_TEMPERATURE - air.react() update_visuals() diff --git a/code/modules/awaymissions/mission_code/beach.dm b/code/modules/awaymissions/mission_code/beach.dm index 0fc750def0b..980dd94765c 100644 --- a/code/modules/awaymissions/mission_code/beach.dm +++ b/code/modules/awaymissions/mission_code/beach.dm @@ -114,9 +114,9 @@ linkedcontroller.decalinpool += A /turf/simulated/floor/beach/away/water/lavaland_air - nitrogen = 14 - oxygen = 8 - temperature = 500 + nitrogen = LAVALAND_NITROGEN + oxygen = LAVALAND_OXYGEN + temperature = LAVALAND_TEMPERATURE planetary_atmos = TRUE /// for boundary "walls" diff --git a/code/modules/awaymissions/mission_code/ruins/oldstation.dm b/code/modules/awaymissions/mission_code/ruins/oldstation.dm index 6561f0bc5fe..7cf6ff16da2 100644 --- a/code/modules/awaymissions/mission_code/ruins/oldstation.dm +++ b/code/modules/awaymissions/mission_code/ruins/oldstation.dm @@ -301,6 +301,16 @@ bound_height = 64 appearance_flags = LONG_GLIDE +/obj/structure/shuttle/engine/huge + name = "engine" + icon = 'icons/obj/3x3.dmi' + icon_state = "huge_engine" + desc = "An extremely large bluespace engine used to propel extremely large ships." + opacity = TRUE + bound_width = 96 + bound_height = 96 + appearance_flags = LONG_GLIDE + // areas //Ruin of ancient Space Station diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 66d1d4ad21e..28575df9f21 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -456,6 +456,7 @@ display_job_bans(TRUE) if(check_rights(R_DEBUG|R_VIEWRUNTIMES, FALSE, mob)) winset(src, "debugmcbutton", "is-disabled=false") + winset(src, "profilecode", "is-disabled=false") /client/proc/is_connecting_from_localhost() var/static/list/localhost_addresses = list("127.0.0.1", "::1") @@ -1258,6 +1259,17 @@ debug_variables(stat_item) message_admins("Admin [key_name_admin(usr)] is debugging the [stat_item] [class].") +/client/proc/try_open_reagent_editor(atom/target) + var/target_UID = target.UID() + var/datum/reagents_editor/editor + // editors is static, it can be accessed using a null reference + editor = editor.editors[target_UID] + if(!editor) + editor = new /datum/reagents_editor(target) + editor.editors[target_UID] = editor + + editor.ui_interact(mob) + #undef LIMITER_SIZE #undef CURRENT_SECOND #undef SECOND_COUNT diff --git a/code/modules/client/preference/character.dm b/code/modules/client/preference/character.dm index 3944fe8ecd1..998f1f3e5b4 100644 --- a/code/modules/client/preference/character.dm +++ b/code/modules/client/preference/character.dm @@ -630,8 +630,10 @@ randomize_eyes_color() if(S.bodyflags & HAS_SKIN_COLOR) randomize_skin_color() - backbag = 2 + backbag = pick(GLOB.backbaglist) age = rand(S.min_age, S.max_age) + physique = pick(GLOB.character_physiques) + height = pick(GLOB.character_heights) /datum/character_save/proc/randomize_hair_color(target = "hair") diff --git a/code/modules/client/preference/link_processing.dm b/code/modules/client/preference/link_processing.dm index 7ed56e99759..961b6394074 100644 --- a/code/modules/client/preference/link_processing.dm +++ b/code/modules/client/preference/link_processing.dm @@ -691,12 +691,12 @@ if("physique") var/new_physique = tgui_input_list(user, "Choose your descriptor for how built your character is on glance.", "Character Preference", GLOB.character_physiques) - if(new_physique) + if(new_physique in GLOB.character_physiques) active_character.physique = new_physique if("height") var/new_height = tgui_input_list(user, "Choose your descriptor for how tall your character is on glance.", "Character Preference", GLOB.character_heights) - if(new_height) + if(new_height in GLOB.character_heights) active_character.height = new_height if("flavor_text") diff --git a/code/modules/client/preference/loadout/loadout_general.dm b/code/modules/client/preference/loadout/loadout_general.dm index 2549eff6d9c..e243d131874 100644 --- a/code/modules/client/preference/loadout/loadout_general.dm +++ b/code/modules/client/preference/loadout/loadout_general.dm @@ -162,11 +162,6 @@ path = /obj/item/paicard cost = 2 -/datum/gear/mob_hunt_game - display_name = "Nano-Mob Hunter GO! Cartridge" - path = /obj/item/cartridge/mob_hunt_game - cost = 2 - ////////////////////// // Mugs // ////////////////////// diff --git a/code/modules/client/preference/loadout/loadout_racial.dm b/code/modules/client/preference/loadout/loadout_racial.dm index 128bfdd3c29..4b576e96daa 100644 --- a/code/modules/client/preference/loadout/loadout_racial.dm +++ b/code/modules/client/preference/loadout/loadout_racial.dm @@ -17,43 +17,11 @@ cost = 1 /datum/gear/racial/taj - display_name = "Embroidered veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." - path = /obj/item/clothing/glasses/tajblind + display_name = "Tajaran veil" + description = "A common traditional nano-fiber veil worn by many Tajaran. It is rare and offensive to see it on other races. Can be combined with various other eyewear." + path = /obj/item/clothing/glasses/hud/tajblind slot = SLOT_HUD_GLASSES -/datum/gear/racial/taj/sec - display_name = "Sleek veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built security HUD." - path = /obj/item/clothing/glasses/hud/security/tajblind - allowed_roles = list("Head of Security", "Warden", "Security Officer", "Internal Affairs Agent", "Magistrate", "Detective") - cost = 2 - -/datum/gear/racial/taj/med - display_name = "Lightweight veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built medical HUD." - path = /obj/item/clothing/glasses/hud/health/tajblind - allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Psychiatrist", "Paramedic", "Virologist", "Coroner") - cost = 2 - -/datum/gear/racial/taj/sci - display_name = "Hi-tech veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." - path = /obj/item/clothing/glasses/tajblind/sci - cost = 2 - -/datum/gear/racial/taj/eng - display_name = "Industrial veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." - path = /obj/item/clothing/glasses/tajblind/eng - cost = 2 - -/datum/gear/racial/taj/cargo - display_name = "Khaki veil" - description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. It is light and comfy!" - path = /obj/item/clothing/glasses/tajblind/cargo - cost = 2 - /datum/gear/racial/footwraps display_name = "Cloth footwraps" path = /obj/item/clothing/shoes/footwraps diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index afbbd575e83..c3193281b5b 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -219,6 +219,8 @@ var/list/color_view = null//overrides client.color while worn var/prescription = FALSE var/prescription_upgradable = FALSE + /// Overrides colorblindness when interacting with wires + var/correct_wires = FALSE var/over_mask = FALSE //Whether or not the eyewear is rendered above the mask. Purely cosmetic. strip_delay = 20 // but seperated to allow items to protect but not impair vision, like space helmets put_on_delay = 25 diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 38667b158bb..3f763b55d91 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -530,51 +530,3 @@ icon_state = "cybereye-red" item_state = "eyepatch" flags = NODROP - -/obj/item/clothing/glasses/tajblind - name = "embroidered veil" - desc = "An Ahdominian made veil that allows the user to see while obscuring their eyes." - icon_state = "tajblind" - item_state = "tajblind" - flags_cover = GLASSESCOVERSEYES - actions_types = list(/datum/action/item_action/toggle) - up = FALSE - tint = FLASH_PROTECTION_NONE - prescription_upgradable = TRUE - - sprite_sheets = list( - "Vox" = 'icons/mob/clothing/species/vox/eyes.dmi', - "Grey" = 'icons/mob/clothing/species/grey/eyes.dmi', - "Drask" = 'icons/mob/clothing/species/drask/eyes.dmi' - ) - -/obj/item/clothing/glasses/tajblind/eng - name = "industrial veil" - icon_state = "tajblind_engi" - item_state = "tajblind_engi" - -/obj/item/clothing/glasses/tajblind/sci - name = "hi-tech veil" - icon_state = "tajblind_sci" - item_state = "tajblind_sci" - -/obj/item/clothing/glasses/tajblind/cargo - name = "khaki veil" - icon_state = "tajblind_cargo" - item_state = "tajblind_cargo" - -/obj/item/clothing/glasses/tajblind/attack_self() - toggle_veil() - -/obj/item/clothing/glasses/proc/toggle_veil() - if(HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED) || usr.incapacitated()) - return - up = !up - if(up) - tint = 3 - else - tint = initial(tint) - to_chat(usr, up ? "You deactivate [src], obscuring your vision." : "You activate [src], allowing you to see.") - var/mob/living/carbon/user = usr - user.update_tint() - user.update_inv_glasses() diff --git a/code/modules/clothing/glasses/hudglasses.dm b/code/modules/clothing/glasses/hudglasses.dm index a87eedd9ea8..b45c9d9c447 100644 --- a/code/modules/clothing/glasses/hudglasses.dm +++ b/code/modules/clothing/glasses/hudglasses.dm @@ -172,41 +172,6 @@ see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE -/obj/item/clothing/glasses/hud/security/tajblind - name = "sleek veil" - desc = "An Ahdominian made veil that allows the user to see while obscuring their eyes. This one has an in-built security HUD." - icon_state = "tajblind_sec" - item_state = "tajblind_sec" - flash_protect = FLASH_PROTECTION_FLASH - flags_cover = GLASSESCOVERSEYES - actions_types = list(/datum/action/item_action/toggle) - up = FALSE - - sprite_sheets = list( - "Vox" = 'icons/mob/clothing/species/vox/eyes.dmi' - ) - -/obj/item/clothing/glasses/hud/security/tajblind/attack_self() - toggle_veil() - -/obj/item/clothing/glasses/hud/health/tajblind - name = "lightweight veil" - desc = "An Ahdominian made veil that allows the user to see while obscuring their eyes. This one has an installed medical HUD." - icon_state = "tajblind_med" - item_state = "tajblind_med" - flags_cover = GLASSESCOVERSEYES - actions_types = list(/datum/action/item_action/toggle) - up = FALSE - - sprite_sheets = list( - "Vox" = 'icons/mob/clothing/species/vox/eyes.dmi', - "Grey" = 'icons/mob/clothing/species/grey/eyes.dmi', - "Drask" = 'icons/mob/clothing/species/drask/eyes.dmi' - ) - -/obj/item/clothing/glasses/hud/health/tajblind/attack_self() - toggle_veil() - /obj/item/clothing/glasses/hud/skills name = "skills HUD" desc = "A heads-up display capable of showing the employment history records of NT crew members." diff --git a/code/modules/clothing/glasses/tajblind.dm b/code/modules/clothing/glasses/tajblind.dm new file mode 100644 index 00000000000..306652a4a9f --- /dev/null +++ b/code/modules/clothing/glasses/tajblind.dm @@ -0,0 +1,193 @@ +#define MODE_OFF "veiled" +#define MODE_NATURAL "natural sight" +#define MODE_CORRECTION "correction" + +/obj/item/clothing/glasses/hud/tajblind + name = "\improper Tajaran veil" + desc = "A sleek, high-tech Tajaran veil, adapted from ancient designs and important to their culture and spirituality.
\ + Can switch between three modes: Sight-blocking veiled mode, transparent natural sight mode and colorblindness correction mode." + icon_state = "tajblind" + item_state = "tajblind" + actions_types = list(/datum/action/item_action/toggle) + color_view = MATRIX_STANDARD + correct_wires = TRUE + var/list/modes = list(MODE_OFF = MODE_NATURAL, MODE_NATURAL = MODE_CORRECTION, MODE_CORRECTION = MODE_OFF) + var/selected_mode = MODE_CORRECTION + + sprite_sheets = list( + "Vox" = 'icons/mob/clothing/species/vox/eyes.dmi', + "Grey" = 'icons/mob/clothing/species/grey/eyes.dmi' + ) + +/obj/item/clothing/glasses/hud/tajblind/attack_self(mob/user) + toggle_veil(user, TRUE) + +/obj/item/clothing/glasses/hud/tajblind/proc/toggle_veil(mob/user, voluntary) + var/mob/living/carbon/human/H = user + selected_mode = modes[selected_mode] + to_chat(user, "[voluntary ? "You turn the veil" : "The veil turns"] [selected_mode ? "to [selected_mode] mode" : "off"][voluntary ? "." : "!"]") + + switch(selected_mode) + if(MODE_OFF) + tint = TINT_BLIND + flash_protect = FLASH_PROTECTION_WELDER + color_view = null + correct_wires = FALSE + + if(MODE_NATURAL) + tint = initial(tint) + flash_protect = initial(flash_protect) + color_view = null + + if(MODE_CORRECTION) + tint = initial(tint) + flash_protect = initial(flash_protect) + color_view = MATRIX_STANDARD + correct_wires = TRUE + + if(ishuman(H) && H.glasses == src) + H.update_sight() + H.update_client_colour() + +/obj/item/clothing/glasses/hud/tajblind/examine_more(mob/user) + . = ..() + . += "Tajaran Veils have long been an important part of their spirituality and culture, suppressed by the Overseers and making a strong return after the civil war. Tajaran believe that to see one’s eyes is to see their soul, and thus the more spiritual Tajara wear veils to conceal their eyes from everyone but the ones closest to them.
\ + These current designs are adapted from recreations of the ancient veils, created by the Alchemists Guild. Technologically advanced and created to help Tajara adapt to life in the larger galactic community, they have systems built-in that allow them to have holographic huds, as well as corrective technology to help Tajaran overcome their genetic tritanopia colour blindness.
\ + Availability on the wider market is highly restricted as a result of their cultural importance, as well as the patent held by the Alchemists Guild, and the lenses are very hard to reverse engineer. Popular theories suggest this as a result of the unique materials available on Adhomai, or the inability to recreate the light conditions of the Tajara homeworld." + +/obj/item/clothing/glasses/hud/tajblind/meson + name = "\improper Tajaran engineering meson veil" + icon_state = "tajblind_engi" + item_state = "tajblind_engi" + +/obj/item/clothing/glasses/hud/tajblind/meson/Initialize() + ..() + desc += "
It has an optical meson scanner integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/meson/equipped(mob/user, slot, initial) + . = ..() + if(slot == SLOT_HUD_GLASSES) + ADD_TRAIT(user, TRAIT_MESON_VISION, "meson_glasses[UID()]") + +/obj/item/clothing/glasses/hud/tajblind/meson/dropped(mob/user) + . = ..() + if(user) + REMOVE_TRAIT(user, TRAIT_MESON_VISION, "meson_glasses[UID()]") + +/obj/item/clothing/glasses/hud/tajblind/meson/cargo + name = "\improper Tajaran mining meson veil" + icon_state = "tajblind_cargo" + item_state = "tajblind_cargo" + +/obj/item/clothing/glasses/hud/tajblind/sci + name = "\improper Tajaran scientific veil" + icon_state = "tajblind_sci" + item_state = "tajblind_sci" + scan_reagents = 1 + actions_types = list(/datum/action/item_action/toggle, /datum/action/item_action/toggle_research_scanner) + +/obj/item/clothing/glasses/hud/tajblind/sci/Initialize() + ..() + desc += "
It has science goggles integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/sci/item_action_slot_check(slot) + if(slot == SLOT_HUD_GLASSES) + return TRUE + +/obj/item/clothing/glasses/hud/tajblind/med + name = "\improper Tajaran medical veil" + icon_state = "tajblind_med" + item_state = "tajblind_med" + hud_types = DATA_HUD_MEDICAL_ADVANCED + examine_extensions = list(EXAMINE_HUD_MEDICAL_READ) + +/obj/item/clothing/glasses/hud/tajblind/med/Initialize() + ..() + desc += "
It has a health HUD integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/sec + name = "\improper Tajaran security veil" + icon_state = "tajblind_sec" + item_state = "tajblind_sec" + hud_types = DATA_HUD_SECURITY_ADVANCED + examine_extensions = list(EXAMINE_HUD_SECURITY_READ) + +/obj/item/clothing/glasses/hud/tajblind/sec/Initialize() + ..() + desc += "
It has a security HUD integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/shaded + name = "shaded Tajaran veil" + flash_protect = FLASH_PROTECTION_FLASH + tint = FLASH_PROTECTION_FLASH + +/obj/item/clothing/glasses/hud/tajblind/shaded/Initialize() + ..() + desc += "
It has an in-built flash protection." + +/obj/item/clothing/glasses/hud/tajblind/shaded/meson + name = "shaded Tajaran engineering meson veil" + icon_state = "tajblind_engi" + item_state = "tajblind_engi" + +/obj/item/clothing/glasses/hud/tajblind/shaded/meson/Initialize() + ..() + desc += "
It has an optical meson scanner integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/shaded/meson/equipped(mob/user, slot, initial) + . = ..() + if(slot == SLOT_HUD_GLASSES) + ADD_TRAIT(user, TRAIT_MESON_VISION, "meson_glasses[UID()]") + +/obj/item/clothing/glasses/hud/tajblind/shaded/meson/dropped(mob/user) + . = ..() + if(user) + REMOVE_TRAIT(user, TRAIT_MESON_VISION, "meson_glasses[UID()]") + + +/obj/item/clothing/glasses/hud/tajblind/shaded/meson/cargo + name = "shaded Tajaran mining meson veil" + icon_state = "tajblind_cargo" + item_state = "tajblind_cargo" + +/obj/item/clothing/glasses/hud/tajblind/shaded/sci + name = "shaded Tajaran scientific veil" + icon_state = "tajblind_sci" + item_state = "tajblind_sci" + scan_reagents = 1 + actions_types = list(/datum/action/item_action/toggle, /datum/action/item_action/toggle_research_scanner) + +/obj/item/clothing/glasses/hud/tajblind/shaded/sci/Initialize() + ..() + desc += "
It has science goggles integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/shaded/sci/item_action_slot_check(slot) + if(slot == SLOT_HUD_GLASSES) + return TRUE + +/obj/item/clothing/glasses/hud/tajblind/shaded/med + name = "shaded Tajaran medical veil" + icon_state = "tajblind_med" + item_state = "tajblind_med" + hud_types = DATA_HUD_MEDICAL_ADVANCED + examine_extensions = list(EXAMINE_HUD_MEDICAL_READ) + +/obj/item/clothing/glasses/hud/tajblind/shaded/med/Initialize() + ..() + desc += "
It has a health HUD integrated into it." + +/obj/item/clothing/glasses/hud/tajblind/shaded/sec + name = "shaded Tajaran security veil" + icon_state = "tajblind_sec" + item_state = "tajblind_sec" + see_in_dark = 1 + hud_types = DATA_HUD_SECURITY_ADVANCED + examine_extensions = list(EXAMINE_HUD_SECURITY_READ) + +/obj/item/clothing/glasses/hud/tajblind/shaded/sec/Initialize() + ..() + desc += "
It has a security HUD integrated into it." + +#undef MODE_OFF +#undef MODE_NATURAL +#undef MODE_CORRECTION diff --git a/code/modules/crafting/tailoring.dm b/code/modules/crafting/tailoring.dm index eca646a91e8..51e0a616a28 100644 --- a/code/modules/crafting/tailoring.dm +++ b/code/modules/crafting/tailoring.dm @@ -305,6 +305,254 @@ reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) category = CAT_CLOTHING +/datum/crafting_recipe/shaded_tajblind + name = "Shaded Tajaran veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/sunglasses = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/sunglasses) + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_tajblind_removal + name = "Shaded Tajaran veil removal" + result = list(/obj/item/clothing/glasses/sunglasses, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_tajblind_removal/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind/shaded) + +/datum/crafting_recipe/engi_tajblind + name = "Tajaran engineering meson veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/meson) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/meson = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/engi_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + blacklist += subtypesof(/obj/item/clothing/glasses/meson) + +/datum/crafting_recipe/engi_tajblind_removal + name = "Tajaran engineering meson removal" + result = list(/obj/item/clothing/glasses/meson, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/meson = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/engi_tajblind_removal/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind/meson) + +/datum/crafting_recipe/shaded_engi_tajblind + name = "Shaded Tajaran engineering meson veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded/meson) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/meson/sunglasses = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_engi_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_engi_tajblind_removal + name = "Shaded Tajaran engineering meson veil removal" + result = list(/obj/item/clothing/glasses/meson/sunglasses, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded/meson = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_engi_tajblind_removal/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind/shaded/meson) + +/datum/crafting_recipe/cargo_tajblind + name = "Tajaran mining meson veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/meson/cargo) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/meson = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/cargo_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + blacklist += subtypesof(/obj/item/clothing/glasses/meson) + +/datum/crafting_recipe/cargo_tajblind_removal + name = "Tajaran mining meson veil removal" + result = list(/obj/item/clothing/glasses/meson, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/meson/cargo = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_cargo_tajblind + name = "Shaded Tajaran mining meson veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded/meson/cargo) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/meson/sunglasses = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_cargo_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_cargo_tajblind_removal + name = "Shaded Tajaran mining meson veil removal" + result = list(/obj/item/clothing/glasses/meson/sunglasses, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded/meson/cargo = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/sci_tajblind + name = "Tajaran scientific veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/sci) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/science = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/sci_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/sci_tajblind_removal + name = "Tajaran scientific veil removal" + result = list(/obj/item/clothing/glasses/science, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/sci = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_sci_tajblind + name = "Shaded Tajaran scientific veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded/sci) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_sci_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_sci_tajblind_removal + name = "Shaded Tajaran scientific veil removal" + result = list(/obj/item/clothing/glasses/sunglasses/reagent, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded/sci = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/med_tajblind + name = "Tajaran medical veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/med) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/health = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/med_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + blacklist += subtypesof(/obj/item/clothing/glasses/hud/health) + +/datum/crafting_recipe/med_tajblind_removal + name = "Tajaran medical veil removal" + result = list(/obj/item/clothing/glasses/hud/health, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/med = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_med_tajblind + name = "Shaded Tajaran medical veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded/med) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/health/sunglasses = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_med_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_med_tajblind_removal + name = "Shaded Tajaran medical veil removal" + result = list(/obj/item/clothing/glasses/hud/health/sunglasses, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded/med = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/sec_tajblind + name = "Tajaran security veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/sec) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/security = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/sec_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + blacklist += subtypesof(/obj/item/clothing/glasses/hud/security) + +/datum/crafting_recipe/sec_tajblind_removal + name = "Tajaran security veil removal" + result = list(/obj/item/clothing/glasses/hud/security, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/sec = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_sec_tajblind + name = "Shaded Tajaran security veil" + result = list(/obj/item/clothing/glasses/hud/tajblind/shaded/sec) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1, + /obj/item/clothing/glasses/hud/tajblind = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/shaded_sec_tajblind/New() + ..() + blacklist += subtypesof(/obj/item/clothing/glasses/hud/tajblind) + +/datum/crafting_recipe/shaded_sec_tajblind_removal + name = "Shaded Tajaran security veil removal" + result = list(/obj/item/clothing/glasses/hud/security/sunglasses, /obj/item/clothing/glasses/hud/tajblind) + time = 2 SECONDS + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/clothing/glasses/hud/tajblind/shaded/sec = 1) + category = CAT_CLOTHING + /datum/crafting_recipe/ghostsheet name = "Ghost Sheet" result = list(/obj/item/clothing/suit/ghost_sheet) diff --git a/code/modules/economy/merch_items.dm b/code/modules/economy/merch_items.dm index 4b2c97487d5..b15a0eb6b30 100644 --- a/code/modules/economy/merch_items.dm +++ b/code/modules/economy/merch_items.dm @@ -47,13 +47,6 @@ cost = 100 category = MERCH_CAT_TOY -/datum/merch_item/nanomob_booster - name = "Nano-Mob Hunter Trading Card Booster Pack" - desc = "Contains 6 random Nano-Mob Hunter Trading Cards. May contain a holographic card!" - typepath = /obj/item/storage/box/nanomob_booster_pack - cost = 125 - category = MERCH_CAT_TOY - /datum/merch_item/crayons name = "Crayons" desc = "Let security know how they're doing by scrawling love notes all over their hallways." diff --git a/code/modules/events/blob/blob_mobs.dm b/code/modules/events/blob/blob_mobs.dm index 84061c55058..8a7bb881dfc 100644 --- a/code/modules/events/blob/blob_mobs.dm +++ b/code/modules/events/blob/blob_mobs.dm @@ -84,6 +84,7 @@ if(istype(linked_node)) factory = linked_node factory.spores += src + GLOB.spores_active++ /mob/living/simple_animal/hostile/blob/blobspore/Life(seconds, times_fired) @@ -151,6 +152,7 @@ if(oldguy) oldguy.forceMove(get_turf(src)) oldguy = null + GLOB.spores_active-- return ..() diff --git a/code/modules/events/blob/blob_structures/factory.dm b/code/modules/events/blob/blob_structures/factory.dm index 6bbf5d34f59..13d7e44a9ec 100644 --- a/code/modules/events/blob/blob_structures/factory.dm +++ b/code/modules/events/blob/blob_structures/factory.dm @@ -1,3 +1,5 @@ +GLOBAL_VAR_INIT(spores_active, 0) +#define MAX_GLOBAL_SPORES 25 /obj/structure/blob/factory name = "factory blob" icon = 'icons/mob/blob.dmi' @@ -5,7 +7,7 @@ max_integrity = 200 point_return = 18 var/list/spores = list() - var/max_spores = 3 + var/max_spores = 5 var/spore_delay = 0 /obj/structure/blob/factory/Destroy() @@ -16,12 +18,14 @@ return ..() /obj/structure/blob/factory/run_action() - if(length(spores) >= max_spores) + if(length(spores) >= max_spores || GLOB.spores_active >= MAX_GLOBAL_SPORES) return if(spore_delay > world.time) return flick("blob_factory_glow", src) - spore_delay = world.time + 100 // 10 seconds + spore_delay = world.time + 10 SECONDS var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src) if(overmind) overmind.add_mob_to_overmind(BS) + +#undef MAX_GLOBAL_SPORES diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index 62b4840f32b..490290d28db 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -20,7 +20,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 new /obj/effect/immovablerod/event(startT, endT) /obj/effect/immovablerod - name = "Immovable Rod" + name = "\improper Immovable Rod" desc = "What the fuck is that?" icon = 'icons/obj/objects.dmi' icon_state = "immrod" @@ -28,23 +28,28 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 density = TRUE anchored = TRUE var/z_original = 0 - var/destination var/notify = TRUE var/move_delay = 1 + var/atom/start + var/atom/end -/obj/effect/immovablerod/New(atom/start, atom/end, delay) +/obj/effect/immovablerod/New(atom/_start, atom/_end, delay) . = ..() + start = _start + end = _end loc = start z_original = z - destination = end move_delay = delay if(notify) notify_ghosts("\A [src] is inbound!", enter_link="(Click to follow)", source = src, action = NOTIFY_FOLLOW) GLOB.poi_list |= src + head_towards_dest() + +/obj/effect/immovablerod/proc/head_towards_dest() if(end?.z == z_original) - walk_towards(src, destination, move_delay) + walk_towards(src, end, move_delay) /obj/effect/immovablerod/Topic(href, href_list) if(href_list["follow"]) @@ -76,13 +81,13 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 if(isturf(clong) || isobj(clong)) if(clong.density) - clong.ex_act(2) + clong.ex_act(EXPLODE_HEAVY) else if(ismob(clong)) if(ishuman(clong)) var/mob/living/carbon/human/H = clong - H.visible_message("[H.name] is penetrated by an immovable rod!" , - "The rod penetrates you!" , + H.visible_message("[H.name] is penetrated by an immovable rod!", + "The rod penetrates you!", "You hear a CLANG!") H.adjustBruteLoss(160) if(clong.density || prob(10)) @@ -100,12 +105,34 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 var/turf/simulated/floor/T = get_turf(oldloc) if(istype(T)) T.ex_act(EXPLODE_HEAVY) - if(loc == destination) + if(loc == end) qdel(src) /obj/effect/immovablerod/deadchat_plays(mode = DEADCHAT_DEMOCRACY_MODE, cooldown = 6 SECONDS) return AddComponent(/datum/component/deadchat_control/immovable_rod, mode, list(), cooldown) +/obj/effect/immovablerod/smite + /// The target that we're gonna aim for between start and end + var/obj/effect/portal/exit + +/obj/effect/immovablerod/smite/New(atom/_start, atom/_end) + new /obj/effect/portal(start, lifespan = 2 SECONDS) + return ..() + +/obj/effect/immovablerod/smite/Move() + var/atom/oldloc = loc + . = ..() + if(get_turf(src) == get_turf(end)) + // our exit condition: get outta there kowalski + var/target_turf = get_ranged_target_turf(src, dir, rand(1, 10)) + start = loc + walk(src, 0) + exit = new /obj/effect/portal(target_turf, lifespan = 2 SECONDS) + walk_towards(src, exit, move_delay) + else if(locate(exit) in get_turf(src)) + QDEL_NULL(exit) + qdel(src) + /** * Rod will walk towards edge turf in the specified direction. * @@ -113,5 +140,5 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 * * direction - The direction to walk the rod towards: NORTH, SOUTH, EAST, WEST. */ /obj/effect/immovablerod/proc/walk_in_direction(direction) - destination = get_edge_target_turf(src, direction) - walk_towards(src, destination) + end = get_edge_target_turf(src, direction) + walk_towards(src, end, move_delay) diff --git a/code/modules/food_and_drinks/food/foods/baked_goods.dm b/code/modules/food_and_drinks/food/foods/baked_goods.dm index 903e25d32db..dfcfbf50f4b 100644 --- a/code/modules/food_and_drinks/food/foods/baked_goods.dm +++ b/code/modules/food_and_drinks/food/foods/baked_goods.dm @@ -16,6 +16,7 @@ filling_color = "#FFD675" list_reagents = list("nutriment" = 20, "oculine" = 10, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "carrot" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/carrotcakeslice name = "carrot cake slice" @@ -39,6 +40,7 @@ bitesize = 3 list_reagents = list("protein" = 10, "nutriment" = 10, "mannitol" = 10, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "brains" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/braincakeslice name = "brain cake slice" @@ -61,6 +63,7 @@ bitesize = 3 list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 4, "cream cheese" = 3) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/cheesecakeslice name = "cheese cake slice" @@ -83,6 +86,7 @@ filling_color = "#F7EDD5" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "vanilla" = 1, "sweetness" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/plaincakeslice name = "vanilla cake slice" @@ -105,6 +109,7 @@ filling_color = "#FADA8E" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "oranges" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/orangecakeslice name = "orange cake slice" @@ -127,6 +132,7 @@ filling_color = "#FADA8E" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "banana" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/bananacakeslice name = "banana cake slice" @@ -149,6 +155,7 @@ filling_color = "#CBFA8E" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/limecakeslice name = "lime cake slice" @@ -171,6 +178,7 @@ filling_color = "#FAFA8E" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 2, "sourness" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/lemoncakeslice name = "lemon cake slice" @@ -193,6 +201,7 @@ filling_color = "#805930" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 1, "chocolate" = 4) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/chocolatecakeslice name = "chocolate cake slice" @@ -215,6 +224,7 @@ bitesize = 3 list_reagents = list("nutriment" = 20, "sprinkles" = 10, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/birthdaycakeslice name = "birthday cake slice" @@ -237,6 +247,7 @@ filling_color = "#EBF5B8" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("cake" = 5, "sweetness" = 1, "apple" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/applecakeslice name = "apple cake slice" @@ -369,6 +380,7 @@ filling_color = "#43DE18" list_reagents = list("nutriment" = 10, "vitamin" = 2) tastes = list("pie" = 1, "meat" = 1, "acid" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/applepie diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm index e81ee938ff9..89382e1e1b9 100644 --- a/code/modules/food_and_drinks/food/foods/bread.dm +++ b/code/modules/food_and_drinks/food/foods/bread.dm @@ -13,6 +13,7 @@ filling_color = "#FF7575" list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) tastes = list("bread" = 10, "meat" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/meatbreadslice name = "meatbread slice" @@ -32,6 +33,7 @@ filling_color = "#8AFF75" list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5) tastes = list("bread" = 10, "acid" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/xenomeatbreadslice name = "xenomeatbread slice" @@ -39,6 +41,7 @@ icon = 'icons/obj/food/burgerbread.dmi' icon_state = "xenobreadslice" filling_color = "#8AFF75" + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/sliceable/spidermeatbread name = "spider meat loaf" @@ -49,6 +52,7 @@ slices_num = 5 list_reagents = list("protein" = 20, "nutriment" = 10, "toxin" = 15, "vitamin" = 5) tastes = list("bread" = 10, "cobwebs" = 5) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/spidermeatbreadslice name = "spider meat bread slice" @@ -57,6 +61,7 @@ icon_state = "spidermeatslice" tastes = list("bread" = 10, "cobwebs" = 5) list_reagents = list("toxin" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/sliceable/bananabread name = "banana-nut bread" @@ -68,6 +73,7 @@ filling_color = "#EDE5AD" list_reagents = list("banana" = 20, "nutriment" = 20) tastes = list("bread" = 10, "banana" = 5) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/bananabreadslice name = "banana-nut bread slice" @@ -88,6 +94,7 @@ filling_color = "#F7FFE0" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("bread" = 10, "tofu" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/tofubreadslice name = "tofubread slice" @@ -107,6 +114,7 @@ filling_color = "#FFE396" list_reagents = list("nutriment" = 10) tastes = list("bread" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/breadslice name = "bread slice" @@ -128,6 +136,7 @@ filling_color = "#FFF896" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("bread" = 10, "cheese" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/creamcheesebreadslice name = "cream cheese bread slice" @@ -149,6 +158,7 @@ filling_color = "#6F0000" list_reagents = list("nutriment" = 20, "vitamin" = 5) tastes = list("heresy" = 10, "banana" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/banarnarbreadslice name = "banarnarbread slice" @@ -225,6 +235,7 @@ bitesize = 3 list_reagents = list("nutriment" = 3) tastes = list("toast" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/jelliedtoast name = "jellied toast" diff --git a/code/modules/food_and_drinks/food/foods/candy.dm b/code/modules/food_and_drinks/food/foods/candy.dm index 80cbfc5ee20..a6a65499b02 100644 --- a/code/modules/food_and_drinks/food/foods/candy.dm +++ b/code/modules/food_and_drinks/food/foods/candy.dm @@ -125,6 +125,7 @@ filling_color = "#FFFFFF" bitesize = 4 list_reagents = list("sugar" = 15) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/candy/candybar name = "candy" @@ -155,6 +156,7 @@ filling_color = "#FFFFFF" bitesize = 3 list_reagents = list("sugar" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/candy/gummyworm name = "gummy worm" @@ -163,6 +165,7 @@ filling_color = "#FFFFFF" bitesize = 3 list_reagents = list("sugar" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/candy/jellybean name = "jelly bean" @@ -171,6 +174,7 @@ filling_color = "#FFFFFF" bitesize = 3 list_reagents = list("sugar" = 10) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/candy/jawbreaker name = "jawbreaker" diff --git a/code/modules/food_and_drinks/food/foods/frozen.dm b/code/modules/food_and_drinks/food/foods/frozen.dm index dd117fbaecb..89824dd503c 100644 --- a/code/modules/food_and_drinks/food/foods/frozen.dm +++ b/code/modules/food_and_drinks/food/foods/frozen.dm @@ -21,6 +21,7 @@ bitesize = 3 list_reagents = list("nutriment" = 20, "sugar" = 5, "vitamin" = 5, "banana" = 15) tastes = list("cake" = 5, "sweetness" = 2, "banana" = 1, "sad clowns" = 1, "ice-cream" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/frozen/clowncakeslice name = "clown cake slice" @@ -155,6 +156,7 @@ trash = /obj/item/reagent_containers/drinks/sillycup list_reagents = list("water" = 10, "ice" = 5) tastes = list("cold water" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/frozen/snowcone/apple name = "apple snowcone" diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm index e5a34bad7a3..c3341fcaab1 100644 --- a/code/modules/food_and_drinks/food/foods/meat.dm +++ b/code/modules/food_and_drinks/food/foods/meat.dm @@ -47,6 +47,12 @@ desc = "Much meatier than monkey meat." list_reagents = list("nutriment" = 5, "vitamin" = 1) +/obj/item/food/snacks/meat/kangaroo + name = "kangaroo meat" + desc = "Extremely muscular and tender meat." + list_reagents = list("protein" = 4, "iron" = 5, "vitamin" = 1) + tastes = list("a punch in the face" = 1, "fowl" = 3) + /obj/item/food/snacks/meat/monkey //same as plain meat @@ -284,6 +290,7 @@ bitesize = 4 list_reagents = list("nutriment" = 6) tastes = list("cobwebs" = 1, "the colour green" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/boiledspiderleg name = "boiled spider leg" @@ -294,6 +301,7 @@ bitesize = 3 list_reagents = list("nutriment" = 3, "capsaicin" = 2) tastes = list("cobwebs" = 1, "hot peppers" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/wingfangchu name = "wing fang chu" @@ -304,6 +312,7 @@ filling_color = "#43DE18" list_reagents = list("nutriment" = 6, "soysauce" = 5, "vitamin" = 2) tastes = list("soy" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/goliath_steak name = "goliath steak" @@ -314,6 +323,7 @@ trash = null list_reagents = list("protein" = 6, "vitamin" = 2) tastes = list("meat" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/fried_vox name = "Kentucky Fried Vox" @@ -323,6 +333,7 @@ trash = /obj/item/trash/fried_vox list_reagents = list("nutriment" = 3, "protein" = 5) tastes = list("quills" = 1, "the shoal" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE ////////////////////// // Cubes // @@ -553,6 +564,7 @@ slices_num = 6 list_reagents = list("protein" = 24, "nutriment" = 18, "vitamin" = 5) tastes = list("turkey" = 2, "stuffing" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/turkeyslice name = "turkey serving" diff --git a/code/modules/food_and_drinks/food/foods/misc_food.dm b/code/modules/food_and_drinks/food/foods/misc_food.dm index a65b1bcf3fa..7d5b6bcf6b0 100644 --- a/code/modules/food_and_drinks/food/foods/misc_food.dm +++ b/code/modules/food_and_drinks/food/foods/misc_food.dm @@ -277,6 +277,7 @@ bitesize = 3 list_reagents = list("slimejelly" = 5) tastes = list("jelly" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/popcorn name = "popcorn" diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm index 9cdc5cddb6f..9cdfabe8f6e 100644 --- a/code/modules/food_and_drinks/food/foods/pizza.dm +++ b/code/modules/food_and_drinks/food/foods/pizza.dm @@ -16,6 +16,7 @@ icon_state = "margheritapizza" slice_path = /obj/item/food/snacks/margheritapizzaslice list_reagents = list("nutriment" = 30, "tomatojuice" = 6, "vitamin" = 5) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/margheritapizzaslice name = "margherita slice" @@ -34,6 +35,7 @@ slice_path = /obj/item/food/snacks/meatpizzaslice list_reagents = list("protein" = 30, "tomatojuice" = 6, "vitamin" = 8) tastes = list("crust" = 1, "cheese" = 1, "meat" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/meatpizzaslice name = "meat pizza slice" @@ -52,6 +54,7 @@ slice_path = /obj/item/food/snacks/mushroompizzaslice list_reagents = list("plantmatter" = 30, "vitamin" = 5) tastes = list("crust" = 1, "cheese" = 1, "mushroom" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/mushroompizzaslice name = "mushroom pizza slice" @@ -70,6 +73,7 @@ slice_path = /obj/item/food/snacks/vegetablepizzaslice list_reagents = list("plantmatter" = 25, "tomatojuice" = 6, "oculine" = 12, "vitamin" = 5) tastes = list("crust" = 1, "tomato" = 1, "carrot" = 1, "vegetables" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/vegetablepizzaslice name = "vegetable pizza slice" @@ -88,6 +92,7 @@ slice_path = /obj/item/food/snacks/hawaiianpizzaslice list_reagents = list("protein" = 15, "tomatojuice" = 6, "plantmatter" = 20, "pineapplejuice" = 6, "vitamin" = 5) tastes = list("crust" = 1, "cheese" = 1, "pineapple" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/hawaiianpizzaslice name = "hawaiian pizza slice" @@ -107,6 +112,7 @@ list_reagents = list("nutriment" = 40, "vitamin" = 5) //More nutriment because carbs, but it's not any more vitaminicious filling_color = "#ffe45d" tastes = list("crust" = 1, "cheese" = 2, "pasta" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/macpizzaslice name = "mac 'n' cheese pizza slice" @@ -126,6 +132,7 @@ list_reagents = list("protein" = 30, "tomatojuice" = 6, "vitamin" = 8) filling_color = "#ffe45d" tastes = list("cheese" = 3, "pepperoni" = 3, "grease" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/pepperonipizzaslice name = "pepperoni pizza slice" @@ -143,6 +150,7 @@ icon_state = "cheesepizza" slice_path = /obj/item/food/snacks/cheesepizzaslice list_reagents = list("nutriment" = 40, "tomatojuice" = 6, "vitamin" = 5) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/cheesepizzaslice name = "cheese pizza slice" @@ -161,6 +169,7 @@ slice_path = /obj/item/food/snacks/donkpocketpizzaslice list_reagents = list("nutriment" = 35, "tomatojuice" = 6, "vitamin" = 2, "weak_omnizine" = 6) tastes = list("crust" = 1, "meat" = 1, "laziness" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/donkpocketpizzaslice name = "donk-pocket pizza slice" @@ -179,6 +188,7 @@ slice_path = /obj/item/food/snacks/dankpizzaslice list_reagents = list("nutriment" = 30, "tomatojuice" = 6, "vitamin" = 5, "cbd" = 6, "thc" = 6) tastes = list("crust" = 1, "cheese" = 1, "special herbs" = 2) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/dankpizzaslice name = "dank pizza slice" @@ -197,6 +207,7 @@ slice_path = /obj/item/food/snacks/firecrackerpizzaslice list_reagents = list("nutriment" = 30, "vitamin" = 5, "capsaicin" = 12) tastes = list("crust" = 1, "cheese" = 1, "HOTNESS" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/firecrackerpizzaslice name = "firecracker pizza slice" @@ -215,6 +226,7 @@ slice_path = /obj/item/food/snacks/pestopizzaslice list_reagents = list("nutriment" = 30, "tomatojuice" = 12, "vitamin" = 5, "wasabi" = 12) tastes = list("tomato" = 1, "cheese" = 1, "wasabi" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/pestopizzaslice name = "\"pesto\" pizza slice" @@ -233,6 +245,7 @@ slice_path = /obj/item/food/snacks/garlicpizzaslice list_reagents = list("plantmatter" = 30, "vitamin" = 5, "garlic" = 12) tastes = list("crust" = 1, "cheese" = 1, "garlic" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/garlicpizzaslice name = "garlic pizza slice" diff --git a/code/modules/food_and_drinks/food/foods/sandwiches.dm b/code/modules/food_and_drinks/food/foods/sandwiches.dm index 77f1a8092ec..cefe18469af 100644 --- a/code/modules/food_and_drinks/food/foods/sandwiches.dm +++ b/code/modules/food_and_drinks/food/foods/sandwiches.dm @@ -38,6 +38,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "ectoplasm" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/human var/hname = "" @@ -93,6 +94,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "acid" = 4) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/clown name = "clown burger" @@ -102,6 +104,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "banana" = 1, "magic" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/mime name = "mime burger" @@ -111,6 +114,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "silence" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/baseball name = "home run baseball burger" @@ -120,6 +124,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "a homerun" = 3) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/spell name = "spell burger" @@ -129,6 +134,7 @@ bitesize = 3 list_reagents = list("nutriment" = 6, "vitamin" = 1) tastes = list("bun" = 4, "magic" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/bigbite name = "BigBite burger" @@ -148,6 +154,7 @@ bitesize = 7 list_reagents = list("nutriment" = 40, "vitamin" = 5) tastes = list("bun" = 4, "meat" = 2, "cheese" = 2, "type two diabetes" = 10) + goal_difficulty = FOOD_GOAL_HARD /obj/item/food/snacks/burger/crazy name = "crazy hamburger" @@ -157,6 +164,7 @@ bitesize = 3 list_reagents = list("nutriment" = 10, "vitamin" = 2, "capsaicin" = 3, "condensedcapsaicin" = 2) tastes = list("bun" = 2, "meat" = 4, "cheese" = 2, "beef soaked in chili" = 3, "a smoking flare" = 2) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/ppatty/white name = "white pretty patty" @@ -285,6 +293,7 @@ bitesize = 3 list_reagents = list("nutriment" = 3, "protein" = 6, "vitamin" = 2) tastes = list("bun" = 1, "meat" = 1, "salmon" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/burger/fivealarm name = "five alarm burger" @@ -401,6 +410,7 @@ icon_state = "notasandwich" list_reagents = list("nutriment" = 6, "vitamin" = 6) tastes = list("nothing suspicious" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/wrap name = "egg wrap" diff --git a/code/modules/food_and_drinks/food/foods/seafood.dm b/code/modules/food_and_drinks/food/foods/seafood.dm index 69f88b307ec..a4529b88ae0 100644 --- a/code/modules/food_and_drinks/food/foods/seafood.dm +++ b/code/modules/food_and_drinks/food/foods/seafood.dm @@ -149,6 +149,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("shrimp" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Ebi name = "ebi sushi" @@ -170,6 +171,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8, "protein" = 4) tastes = list("salmon roe" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Ikura name = "ikura sushi" @@ -191,6 +193,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("raw salmon" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Sake name = "sake sushi" @@ -212,6 +215,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("smoked salmon" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_SmokedSalmon name = "smoked salmon sushi" @@ -233,6 +237,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("egg" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Tamago name = "tamago sushi" @@ -254,6 +259,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("fried tofu" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Inari name = "inari sushi" @@ -275,6 +281,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8, "protein" = 4) tastes = list("goldfish roe" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Masago name = "masago sushi" @@ -296,6 +303,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8, "protein" = 4) tastes = list("shark roe" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Tobiko name = "tobiko sushi" @@ -317,6 +325,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8, "protein" = 4) tastes = list("shark roe" = 1, "rice" = 1, "egg" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_TobikoEgg name = "tobiko and egg sushi" @@ -338,6 +347,7 @@ bitesize = 3 list_reagents = list("nutriment" = 8) tastes = list("catfish" = 1, "rice" = 1, "seaweed" = 1) + goal_difficulty = FOOD_GOAL_DUPLICATE /obj/item/food/snacks/sushi_Tai name = "tai sushi" diff --git a/code/modules/food_and_drinks/food/foods/soups.dm b/code/modules/food_and_drinks/food/foods/soups.dm index e2c4df37a92..e7b4db67565 100644 --- a/code/modules/food_and_drinks/food/foods/soups.dm +++ b/code/modules/food_and_drinks/food/foods/soups.dm @@ -47,6 +47,7 @@ filling_color = "#C4FBFF" list_reagents = list("nutriment" = 4, "banana" = 5, "water" = 5, "vitamin" = 8) tastes = list("a bad joke" = 1) + goal_difficulty = FOOD_GOAL_EXCESSIVE /obj/item/food/snacks/soup/vegetablesoup name = "vegetable soup" @@ -317,3 +318,4 @@ filling_color = "#FF3C00" list_reagents = list("nutriment" = 5, "tomatojuice" = 2, "protein" = 2) tastes = list("tomato" = 1, "chili" = 1, "meat" = 1, "sad clowns" = 4) + goal_difficulty = FOOD_GOAL_EXCESSIVE diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index cccfab34edc..4f47e4a8863 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -180,6 +180,8 @@ . += "Alt-click to put something small inside." /obj/item/food/snacks/sliceable/AltClick(mob/user) + if(!Adjacent(user)) + return var/obj/item/I = user.get_active_hand() if(!I) return diff --git a/code/modules/food_and_drinks/food_base.dm b/code/modules/food_and_drinks/food_base.dm index d748c00e5bd..21c53fbad00 100644 --- a/code/modules/food_and_drinks/food_base.dm +++ b/code/modules/food_and_drinks/food_base.dm @@ -29,9 +29,9 @@ var/temperature_min = 0 // To limit the temperature of a reagent container can attain when exposed to heat/cold var/temperature_max = 10000 - // How difficult is this food for the kitchen to make? - // Affects the quantity of food that is requested by CC. - var/goal_difficulty = REAGENT_GOAL_SKIP + /// How difficult is this food for the kitchen to make? + /// Affects the quantity of food that is requested by CC. + var/goal_difficulty = FOOD_GOAL_SKIP /obj/item/food/Initialize(mapload) . = ..() diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm index 6364f1629b0..98f22590080 100644 --- a/code/modules/hydroponics/grown/towercap.dm +++ b/code/modules/hydroponics/grown/towercap.dm @@ -16,6 +16,7 @@ icon_dead = "towercap-dead" genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism) mutatelist = list(/obj/item/seeds/tower/steel) + reagents_add = list("carbon" = 0.2) /obj/item/seeds/tower/steel name = "pack of steel-cap mycelium" @@ -25,6 +26,7 @@ plantname = "Steel Caps" product = /obj/item/grown/log/steel mutatelist = list() + reagents_add = list("iron" = 0.5) rarity = 20 diff --git a/code/modules/martial_arts/combos/judo/goldenblast.dm b/code/modules/martial_arts/combos/judo/goldenblast.dm new file mode 100644 index 00000000000..7e46aeb4cc6 --- /dev/null +++ b/code/modules/martial_arts/combos/judo/goldenblast.dm @@ -0,0 +1,21 @@ +/datum/martial_combo/judo/goldenblast + // This is incredibly stupid. I love it. + name = "Golden Blast" + steps = list(MARTIAL_COMBO_STEP_HELP, MARTIAL_COMBO_STEP_DISARM, MARTIAL_COMBO_STEP_HELP, MARTIAL_COMBO_STEP_GRAB, MARTIAL_COMBO_STEP_DISARM, MARTIAL_COMBO_STEP_DISARM, MARTIAL_COMBO_STEP_GRAB, MARTIAL_COMBO_STEP_HELP, MARTIAL_COMBO_STEP_DISARM, MARTIAL_COMBO_STEP_DISARM, MARTIAL_COMBO_STEP_GRAB, MARTIAL_COMBO_STEP_HELP) + explaination_text = "Through use of a martial arts form, you can stun a foe with life energy. Or by overcharging the belt's nanites. Take your Pick." + combo_text_override = "Help, Disarm, Help, Grab, Disarm, Disarm, Grab, Help, Disarm, Disarm, Grab, Help" + +/datum/martial_combo/judo/goldenblast/perform_combo(mob/living/carbon/human/user, mob/living/target, datum/martial_art/MA) + target.visible_message("[user] blasts [target] with energy, sending [target.p_them()] to the ground!", \ + "[user] makes strange hand gestures, screams wildly and prods you directly in the chest! You feel the wrath of the GOLDEN BOLT surge through your body! You've been utterly robusted!") + playsound(get_turf(target), 'sound/weapons/taser.ogg', 55, TRUE, -1) + playsound(get_turf(target), 'sound/weapons/tase.ogg', 55, TRUE, -1) + target.SpinAnimation(10, 1) + do_sparks(5, FALSE, target) + user.say("GOLDEN BLAST!") + playsound(get_turf(user), 'sound/weapons/goldenblast.ogg', 60, TRUE, -1) + target.apply_damage(120, STAMINA) + target.KnockDown(30 SECONDS) + target.SetConfused(30 SECONDS) + add_attack_logs(user, target, "Melee attacked with martial-art [src] : Golden Blast", ATKLOG_ALL) + return MARTIAL_COMBO_DONE diff --git a/code/modules/martial_arts/combos/judo/wheelthrow.dm b/code/modules/martial_arts/combos/judo/wheelthrow.dm index 6759093d136..96af978a480 100644 --- a/code/modules/martial_arts/combos/judo/wheelthrow.dm +++ b/code/modules/martial_arts/combos/judo/wheelthrow.dm @@ -11,7 +11,7 @@ "[user] throws you over [user.p_their()] shoulder, slamming you into the ground!") playsound(get_turf(user), 'sound/magic/tail_swing.ogg', 40, TRUE, -1) target.SpinAnimation(10, 1) - target.apply_damage(200, STAMINA) + target.apply_damage(120, STAMINA) target.KnockDown(15 SECONDS) target.SetConfused(10 SECONDS) add_attack_logs(user, target, "Melee attacked with martial-art [src] : Wheel Throw", ATKLOG_ALL) diff --git a/code/modules/martial_arts/judo.dm b/code/modules/martial_arts/judo.dm index 6fc113321b0..15815409870 100644 --- a/code/modules/martial_arts/judo.dm +++ b/code/modules/martial_arts/judo.dm @@ -2,7 +2,7 @@ name = "Corporate Judo" has_explaination_verb = TRUE no_baton = TRUE - combos = list(/datum/martial_combo/judo/discombobulate, /datum/martial_combo/judo/eyepoke, /datum/martial_combo/judo/judothrow, /datum/martial_combo/judo/armbar, /datum/martial_combo/judo/wheelthrow) + combos = list(/datum/martial_combo/judo/discombobulate, /datum/martial_combo/judo/eyepoke, /datum/martial_combo/judo/judothrow, /datum/martial_combo/judo/armbar, /datum/martial_combo/judo/wheelthrow, /datum/martial_combo/judo/goldenblast) weight = 5 //takes priority over boxing and drunkneness, less priority than krav or CQC/carp no_baton_reason = "The baton feels off balance in your hand due to your judo training!" can_horizontally_grab = FALSE diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index c34741ccaaa..b1b44250c9a 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -50,6 +50,7 @@ for(var/t in trophies) var/obj/item/crusher_trophy/T = t . += "It has \a [T] attached, which causes [T.effect_desc()]." + . += "You can use a crowbar on it to remove it's attached trophies." /obj/item/kinetic_crusher/attackby(obj/item/I, mob/living/user) if(istype(I, /obj/item/crusher_trophy)) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 47f9ab77c8c..e4ce7921dca 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -213,7 +213,7 @@ "You insert [I] into [src].") return - else if(istype(I, /obj/item/gripper_engineering)) + else if(istype(I, /obj/item/gripper)) if(!try_refill_storage(user)) to_chat(user, "You fail to retrieve any sheets from [src].") return diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 8d1bfef8a8c..f2a6374bc3d 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -317,11 +317,11 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ spawn(det_time) if(primed) if(quality == GIBTONITE_QUALITY_HIGH) - explosion(src.loc,2,4,9,adminlog = notify_admins) + explosion(loc, 2, 4, 9, adminlog = notify_admins) if(quality == GIBTONITE_QUALITY_MEDIUM) - explosion(src.loc,1,2,5,adminlog = notify_admins) + explosion(loc, 1, 2, 5, adminlog = notify_admins) if(quality == GIBTONITE_QUALITY_LOW) - explosion(src.loc,-1,1,3,adminlog = notify_admins) + explosion(loc, -1, 1, 3, adminlog = notify_admins) qdel(src) diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 33ded157189..984f2d1d138 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -342,7 +342,7 @@ exclaim_verbs = list("imparts") colour = "abductor" key = "^" - flags = RESTRICTED | HIVEMIND | NOLIBRARIAN + flags = RESTRICTED | HIVEMIND | NOLIBRARIAN | HIVEMIND_RUNECHAT follow = TRUE /datum/language/grey/broadcast(mob/living/speaker, message, speaker_mask) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 37a3e94cf27..3d0491e1279 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -7,6 +7,7 @@ maxHealth = 25 health = 25 + butcher_results = list(/obj/item/food/snacks/monstermeat/xenomeat = 1) density = FALSE var/temperature_resistance = T0C+75 diff --git a/code/modules/mob/living/carbon/human/human_emote.dm b/code/modules/mob/living/carbon/human/human_emote.dm index a85c0158ccf..7cb251ab8a4 100644 --- a/code/modules/mob/living/carbon/human/human_emote.dm +++ b/code/modules/mob/living/carbon/human/human_emote.dm @@ -375,6 +375,8 @@ cooldown = 5 SECONDS /// Status effect to apply when this emote is used. Should be a subtype var/status = STATUS_EFFECT_HIGHFIVE + /// title override, used for the re-use message. + var/action_name /datum/emote/living/carbon/human/highfive/can_run_emote(mob/user, status_check, intentional) . = ..() @@ -382,12 +384,17 @@ if(user_carbon.restrained()) return FALSE +/datum/emote/living/carbon/human/highfive/proc/set_status(mob/living/carbon/user) + return user.apply_status_effect(status) + /datum/emote/living/carbon/human/highfive/run_emote(mob/user, params, type_override, intentional) var/mob/living/carbon/user_carbon = user if(user_carbon.has_status_effect(status)) - user.visible_message("[user.name] shakes [user.p_their()] hand around slightly, impatiently waiting for someone to [key].") + user.visible_message("[user.name] shakes [user.p_their()] hand around slightly, impatiently waiting for someone to [!isnull(action_name) ? action_name : key].") + return TRUE + var/datum/result = set_status(user) + if(QDELETED(result)) return TRUE - user_carbon.apply_status_effect(status) return ..() @@ -401,6 +408,39 @@ key_third_person = "handshakes" status = STATUS_EFFECT_HANDSHAKE +/datum/emote/living/carbon/human/highfive/rps + key = "rps" + param_desc = "r,p,s" + hands_use_check = TRUE + status = STATUS_EFFECT_RPS + action_name = "play rock-paper-scissors with" + target_behavior = EMOTE_TARGET_BHVR_IGNORE + /// If the user used parameters, the move that will be made. + var/move + +/datum/emote/living/carbon/human/highfive/rps/run_emote(mob/user, emote_arg, type_override, intentional) + switch(lowertext(emote_arg)) + if("r", "rock") + move = RPS_EMOTE_ROCK + if("p", "paper") + move = RPS_EMOTE_PAPER + if("s", "scissors") + move = RPS_EMOTE_SCISSORS + + // if it's an invalid emote param, just fall through and let them select + + return ..() + +/datum/emote/living/carbon/human/highfive/rps/set_status(mob/living/carbon/user) + if(!isnull(move)) + // if they supplied a valid parameter, use that for the move + return user.apply_status_effect(status, move) + return user.apply_status_effect(status) + +/datum/emote/living/carbon/human/highfive/rps/reset_emote() + ..() + move = initial(move) + /datum/emote/living/carbon/human/snap key = "snap" key_third_person = "snaps" @@ -453,7 +493,6 @@ mob_type_allowed_typecache = list(/mob/living/carbon/human) hands_use_check = TRUE - ///////// // Species-specific emotes diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm index 2c3d81904c3..eade62cabf0 100644 --- a/code/modules/mob/living/carbon/human/human_mob.dm +++ b/code/modules/mob/living/carbon/human/human_mob.dm @@ -1967,7 +1967,3 @@ Eyes need to have significantly high darksight to shine unless the mob has the X set category = "IC" update_flavor_text() - -/mob/living/carbon/human/proc/apply_offstation_roles(source) - SIGNAL_HANDLER - mind.offstation_role = TRUE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b7bb510dc0f..1b6ddb47b94 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -414,6 +414,10 @@ L += contents for(var/obj/item/storage/S in contents) //Check for storage items L += get_contents(S) + for(var/obj/item/mod/control/C in contents) //Check for modsuit storage + for(var/obj/item/mod/module/storage/MS in C.contents) + for(var/obj/item/storage/MSB in MS.contents) + L += get_contents(MSB) for(var/obj/item/clothing/suit/storage/S in contents)//Check for labcoats and jackets L += get_contents(S) for(var/obj/item/clothing/accessory/storage/S in contents)//Check for holsters diff --git a/code/modules/mob/living/silicon/ai/ai_mob.dm b/code/modules/mob/living/silicon/ai/ai_mob.dm index 89ad5bed7c4..b19e498d42e 100644 --- a/code/modules/mob/living/silicon/ai/ai_mob.dm +++ b/code/modules/mob/living/silicon/ai/ai_mob.dm @@ -750,24 +750,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list( to_chat(src, "Target is not on or near any active cameras on the station.") return - if(href_list["callbot"]) //Command a bot to move to a selected location. - Bot = locate(href_list["callbot"]) in GLOB.bots_list - if(!Bot || Bot.remote_disabled || control_disabled) - return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off. - waypoint_mode = TRUE - to_chat(src, "Set your waypoint by clicking on a valid location free of obstructions.") - return - - if(href_list["interface"]) //Remotely connect to a bot! - Bot = locate(href_list["interface"]) in GLOB.bots_list - if(!Bot || Bot.remote_disabled || control_disabled) - return - Bot.attack_ai(src) - - if(href_list["botrefresh"]) //Refreshes the bot control panel. - botcall() - return - if(href_list["ai_take_control"]) //Mech domination var/obj/mecha/M = locate(href_list["ai_take_control"]) @@ -832,26 +814,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list( if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) return - var/d - var/area/bot_area - d += "Query network status
" - d += "" - - for(var/mob/living/simple_animal/bot/Bot in GLOB.bots_list) - if(is_ai_allowed(Bot.z) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected! - bot_area = get_area(Bot) - d += "" - //If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all. - d += "" - d += "" - d += "" - d += "" - d += "" - d = format_text(d) - - var/datum/browser/popup = new(src, "botcall", "Remote Robot Control", 700, 400) - popup.set_content(d) - popup.open() + var/datum/ui_module/botcall/botcall + botcall = new(src) + botcall.ui_interact(usr) /mob/living/silicon/ai/proc/set_waypoint(atom/A) var/turf/turf_check = get_turf(A) diff --git a/code/modules/mob/living/silicon/ai/ai_verbs/botcall.dm b/code/modules/mob/living/silicon/ai/ai_verbs/botcall.dm new file mode 100644 index 00000000000..63075b541d6 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_verbs/botcall.dm @@ -0,0 +1,41 @@ +/datum/ui_module/botcall + name = "Access Robot Control" + + var/mob/living/simple_animal/bot/bot + var/mob/living/silicon/ai/AI + +/datum/ui_module/botcall/ui_state(mob/user) + return GLOB.default_state + +/datum/ui_module/botcall/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BotCall") + ui.set_autoupdate(TRUE) + ui.open() + +/datum/ui_module/botcall/ui_data(mob/user) + var/list/data = ..() + data["bots"] = list() + for(bot in GLOB.bots_list) + if(is_ai_allowed(bot.z) && !bot.remote_disabled) + if(!(bot.bot_type in data["bots"])) + data["bots"][bot.bot_type] = list() + data["bots"][bot.bot_type] += list(bot.get_bot_data()) + return data + +/datum/ui_module/botcall/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return + var/selected_UID = params["botref"] + AI = usr + bot = locateUID(selected_UID) + if(!bot || bot.remote_disabled || AI.control_disabled) + return + switch(action) + if("interface") + bot.attack_ai(usr) + if("call") + AI.Bot = bot + AI.waypoint_mode = TRUE + to_chat(AI, "Set your waypoint by clicking on a valid location free of obstructions.") diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index 09e6f0a9abe..af236704920 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -1,162 +1,3 @@ -//Simple borg hand. -//Limited use. -/// This isn't a drone item, also in engineering cyborg kits -/obj/item/gripper_engineering - name = "magnetic gripper" - desc = "A simple grasping tool for synthetic assets." - icon = 'icons/obj/device.dmi' - icon_state = "gripper" - actions_types = list(/datum/action/item_action/drop_gripped_item) - - //Has a list of items that it can hold. - var/list/can_hold = list( - /obj/item/firealarm_electronics, - /obj/item/airalarm_electronics, - /obj/item/airlock_electronics, - /obj/item/firelock_electronics, - /obj/item/intercom_electronics, - /obj/item/apc_electronics, - /obj/item/tracker_electronics, - /obj/item/stock_parts, - /obj/item/vending_refill, - /obj/item/mounted/frame/light_fixture, - /obj/item/mounted/frame/apc_frame, - /obj/item/mounted/frame/alarm_frame, - /obj/item/mounted/frame/firealarm, - /obj/item/mounted/frame/display/newscaster_frame, - /obj/item/mounted/frame/intercom, - /obj/item/mounted/frame/extinguisher, - /obj/item/mounted/frame/light_switch, - /obj/item/assembly/prox_sensor, - /obj/item/rack_parts, - /obj/item/camera_assembly, - /obj/item/tank, - /obj/item/circuitboard, - /obj/item/stack/tile/light, - /obj/item/stack/ore/bluespace_crystal, - /obj/item/assembly/igniter, - /obj/item/light - ) - - //Item currently being held. - var/obj/item/gripped_item = null - -/obj/item/gripper_medical - name = "medical gripper" - desc = "A grasping tool used to help patients up once surgery is complete, or to substitute for hands in surgical operations." - icon = 'icons/obj/device.dmi' - icon_state = "gripper" - - -/obj/item/gripper_medical/afterattack(atom/target, mob/living/user, proximity, params) - if(!proximity || !target || !ishuman(target)) - return - var/mob/living/carbon/human/pickup_target = target - if(!IS_HORIZONTAL(pickup_target)) - return - pickup_target.AdjustSleeping(-10 SECONDS) - pickup_target.AdjustParalysis(-6 SECONDS) - pickup_target.AdjustStunned(-6 SECONDS) - pickup_target.AdjustWeakened(-6 SECONDS) - pickup_target.AdjustKnockDown(-6 SECONDS) - pickup_target.stand_up() - playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - user.visible_message( \ - "[user] shakes [pickup_target] trying to wake [pickup_target.p_them()] up!",\ - "You shake [pickup_target] trying to wake [pickup_target.p_them()] up!",\ - ) - -/obj/item/gripper_engineering/Initialize(mapload) - . = ..() - can_hold = typecacheof(can_hold) - -/obj/item/gripper_engineering/ui_action_click(mob/user) - drop_gripped_item() - -/obj/item/gripper_engineering/attack_self(mob/user) - if(!gripped_item) - to_chat(user, "[src] is empty.") - return - gripped_item.attack_self(user) - -/obj/item/gripper_engineering/proc/drop_gripped_item(silent = FALSE) - if(!gripped_item) - return - if(!silent) - to_chat(loc, "You drop [gripped_item].") - gripped_item.forceMove(get_turf(src)) - gripped_item = null - -/obj/item/gripper_engineering/attack(mob/living/carbon/M, mob/living/carbon/user) - return - -/// Grippers are snowflakey so this is needed to to prevent forceMoving grippers after `if(!user.drop_item())` checks done in certain attackby's. // What does this even MEAN - GDN -/obj/item/gripper_engineering/forceMove(atom/destination) - return - -/obj/item/gripper_engineering/afterattack(atom/target, mob/living/user, proximity, params) - if(!target || !proximity) //Target is invalid or we are not adjacent. - return FALSE - - if(gripped_item) //Already have an item. - - //Pass the attack on to the target. This might delete/relocate gripped_item. - if(!target.attackby(gripped_item, user, params)) - // If the attackby didn't resolve or delete the target or gripped_item, afterattack - // (Certain things, such as mountable frames, rely on afterattack) - gripped_item?.afterattack(target, user, 1, params) - - //If gripped_item either didn't get deleted, or it failed to be transfered to its target - if(!gripped_item && length(contents)) - gripped_item = contents[1] - return FALSE - else if(gripped_item && !length(contents)) - gripped_item = null - - else if(isitem(target)) //Check that we're not pocketing a mob. - var/obj/item/I = target - if(is_type_in_typecache(I, can_hold)) // Make sure the item is something the gripper can hold - to_chat(user, "You collect [I].") - I.forceMove(src) - gripped_item = I - else - to_chat(user, "Your gripper cannot hold [target].") - return FALSE - - else if(istype(target,/obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = target - if(A.opened) - if(A.cell) - - gripped_item = A.cell - - A.cell.add_fingerprint(user) - A.cell.update_icon() - A.cell.forceMove(src) - A.cell = null - - A.charging = APC_NOT_CHARGING - A.update_icon() - - user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.") - - else if(istype(target, /obj/machinery/cell_charger)) - var/obj/machinery/cell_charger/cell_charger = target - if(cell_charger.charging) - gripped_item = cell_charger.charging - cell_charger.charging.add_fingerprint(user) - cell_charger.charging.forceMove(src) - cell_charger.removecell() - - else if(istype(target, /obj/machinery/light)) - var/obj/machinery/light/light = target - var/obj/item/light/L = light.drop_light_tube() - L.forceMove(src) - gripped_item = L - user.visible_message("[user] removes the light from the fixture.", "You dislodge the light from the fixture.") - - return TRUE - /obj/item/matter_decompiler name = "matter decompiler" desc = "Eating trash, bits of glass, or other debris will replenish your stores." diff --git a/code/modules/mob/living/silicon/robot/robot_inventory.dm b/code/modules/mob/living/silicon/robot/robot_inventory.dm index 3e89737f962..29cbd551747 100644 --- a/code/modules/mob/living/silicon/robot/robot_inventory.dm +++ b/code/modules/mob/living/silicon/robot/robot_inventory.dm @@ -116,7 +116,7 @@ return 0 /mob/living/silicon/robot/drop_item() - var/obj/item/gripper_engineering/G = get_active_hand() + var/obj/item/gripper/G = get_active_hand() if(istype(G)) G.drop_gripped_item(silent = TRUE) return TRUE // The gripper is special because it has a normal item inside that we can drop. diff --git a/code/modules/mob/living/silicon/robot/robot_mob.dm b/code/modules/mob/living/silicon/robot/robot_mob.dm index c3dd377d2f7..d95d0d9d294 100644 --- a/code/modules/mob/living/silicon/robot/robot_mob.dm +++ b/code/modules/mob/living/silicon/robot/robot_mob.dm @@ -1698,7 +1698,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( /// Used in `robot.dm` when the user presses "Q" by default. /mob/living/silicon/robot/proc/on_drop_hotkey_press() - var/obj/item/gripper_engineering/G = get_active_hand() + var/obj/item/gripper/G = get_active_hand() if(istype(G) && G.gripped_item) G.drop_gripped_item() // if the active module is a gripper, try to drop its held item. else diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 58345615762..352c05b2808 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -354,7 +354,7 @@ /obj/item/stack/medical/ointment/advanced/cyborg, /obj/item/stack/medical/splint/cyborg, /obj/item/stack/nanopaste/cyborg, - /obj/item/gripper_medical + /obj/item/gripper/medical ) malf_modules = list(/obj/item/gun/syringemalf) special_rechargables = list( @@ -362,6 +362,11 @@ /obj/item/gun/syringemalf ) +/obj/item/robot_module/medical/handle_death(mob/living/silicon/robot/R, gibbed) + var/obj/item/gripper/medical/G = locate(/obj/item/gripper/medical) in modules + if(G) + G.drop_gripped_item(silent = TRUE) + // Disable safeties on the borg's defib. /obj/item/robot_module/medical/emag_act(mob/user) . = ..() @@ -451,7 +456,7 @@ /obj/item/analyzer, /obj/item/geiger_counter/cyborg, /obj/item/holosign_creator/engineering, - /obj/item/gripper_engineering, + /obj/item/gripper/engineering, /obj/item/matter_decompiler, /obj/item/painter, /obj/item/areaeditor/blueprints/cyborg, @@ -471,7 +476,7 @@ special_rechargables = list(/obj/item/extinguisher, /obj/item/weldingtool/largetank/cyborg, /obj/item/gun/energy/emitter/cyborg) /obj/item/robot_module/engineering/handle_death(mob/living/silicon/robot/R, gibbed) - var/obj/item/gripper_engineering/G = locate(/obj/item/gripper_engineering) in modules + var/obj/item/gripper/engineering/G = locate(/obj/item/gripper/engineering) in modules if(G) G.drop_gripped_item(silent = TRUE) @@ -513,7 +518,8 @@ /obj/item/mop/advanced/cyborg, /obj/item/lightreplacer/cyborg, /obj/item/holosign_creator/janitor, - /obj/item/extinguisher/mini + /obj/item/extinguisher/mini, + /obj/item/melee/flyswatter ) emag_override_modules = list(/obj/item/reagent_containers/spray/cyborg_lube) emag_modules = list(/obj/item/reagent_containers/spray/cyborg_facid, /obj/item/malfbroom) @@ -603,7 +609,8 @@ /obj/item/reagent_containers/dropper/cyborg, /obj/item/lighter/zippo, /obj/item/storage/bag/tray/cyborg, - /obj/item/reagent_containers/drinks/shaker + /obj/item/reagent_containers/drinks/shaker, + /obj/item/gripper/service ) emag_override_modules = list(/obj/item/reagent_containers/drinks/cans/beer/sleepy_beer) emag_modules = list(/obj/item/restraints/handcuffs/cable/zipties/cyborg, /obj/item/instrument/guitar/cyborg) @@ -614,6 +621,10 @@ /obj/item/gun/projectile/shotgun/automatic/combat/cyborg ) +/obj/item/robot_module/butler/handle_death(mob/living/silicon/robot/R, gibbed) + var/obj/item/gripper/service/G = locate(/obj/item/gripper/service) in modules + if(G) + G.drop_gripped_item(silent = TRUE) // This is a special type of beer given when emagged, one sip and the target falls asleep. /obj/item/reagent_containers/drinks/cans/beer/sleepy_beer @@ -705,7 +716,7 @@ /obj/item/gun/projectile/revolver/grenadelauncher/multi/cyborg, /obj/item/card/emag, /obj/item/crowbar/cyborg/red, - /obj/item/pinpointer/operative + /obj/item/pinpointer/operative, ) // Sydicate medical cyborg module. @@ -738,7 +749,7 @@ /obj/item/stack/nanopaste/cyborg/syndicate, /obj/item/gun/medbeam, /obj/item/extinguisher/mini, - /obj/item/gripper_medical + /obj/item/gripper/medical, ) special_rechargables = list(/obj/item/extinguisher/mini) @@ -759,7 +770,7 @@ /obj/item/multitool/cyborg, /obj/item/t_scanner, /obj/item/analyzer, - /obj/item/gripper_engineering, + /obj/item/gripper/engineering, /obj/item/melee/energy/sword/cyborg, /obj/item/card/emag, /obj/item/borg_chameleon, @@ -845,7 +856,7 @@ /obj/item/wirecutters/cyborg/drone, /obj/item/multitool/cyborg/drone, /obj/item/lightreplacer/cyborg, - /obj/item/gripper_engineering, + /obj/item/gripper/engineering, /obj/item/matter_decompiler, /obj/item/reagent_containers/spray/cleaner/drone, /obj/item/soap, @@ -869,7 +880,7 @@ ) /obj/item/robot_module/drone/handle_death(mob/living/silicon/robot/R, gibbed) - var/obj/item/gripper_engineering/G = locate(/obj/item/gripper_engineering) in modules + var/obj/item/gripper/engineering/G = locate(/obj/item/gripper/engineering) in modules if(G) G.drop_gripped_item(silent = TRUE) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 9c8819b2a11..cfc7a597101 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -30,6 +30,8 @@ var/window_height = 0 var/obj/item/paicard/paicard // Inserted pai card. var/allow_pai = TRUE // Are we even allowed to insert a pai card. + + /// storing bot_name prior to pai and restoring it. MULEBOT uses this for suffix system var/bot_name var/disabling_timer_id = null @@ -116,8 +118,8 @@ /// The radio filter the bot uses to identify itself on the network. var/bot_filter - /// The type of bot it is, for radio control. - var/bot_type = 0 + /// Type of bot, one of the *_BOT defines. + var/bot_type /// The type of data HUD the bot uses. Diagnostic by default. var/data_hud_type = DATA_HUD_DIAGNOSTIC_BASIC // This holds text for what the bot is mode doing, reported on the remote bot control interface. @@ -398,51 +400,63 @@ if(allowed(user) && !open && !emagged) locked = !locked to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]") + return + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "Access denied.") - else if(istype(W, /obj/item/paicard)) + to_chat(user, "Access denied.") + return + + if(istype(W, /obj/item/paicard)) if(paicard) to_chat(user, "A [paicard] is already inserted!") - else if(allow_pai && !key) - if(!locked && !open && !hijacked) - var/obj/item/paicard/card = W - if(card.pai && card.pai.mind) - if(!card.pai.ckey || jobban_isbanned(card.pai, ROLE_SENTIENT)) - to_chat(user, "[W] is unable to establish a connection to [src].") - return - if(!user.drop_item()) - return - W.forceMove(src) - paicard = card - user.visible_message("[user] inserts [W] into [src]!","You insert [W] into [src].") - paicard.pai.mind.transfer_to(src) - to_chat(src, "You sense your form change as you are uploaded into [src].") - bot_name = name - name = paicard.pai.name - faction = user.faction - add_attack_logs(user, paicard.pai, "Uploaded to [src.bot_name]") - else - to_chat(user, "[W] is inactive.") - else - to_chat(user, "The personality slot is locked.") - else + return + + if(!allow_pai || key) to_chat(user, "[src] is not compatible with [W].") - else if(istype(W, /obj/item/hemostat) && paicard) + return + + if(locked || open || hijacked) + to_chat(user, "The personality slot is locked.") + return + + var/obj/item/paicard/card = W + if(!card.pai?.mind) + to_chat(user, "[W] is inactive.") + return + + if(!card.pai.ckey || jobban_isbanned(card.pai, ROLE_SENTIENT)) + to_chat(user, "[W] is unable to establish a connection to [src].") + return + + if(!user.drop_item()) + return + + W.forceMove(src) + paicard = card + user.visible_message("[user] inserts [W] into [src]!", "You insert [W] into [src].") + paicard.pai.mind.transfer_to(src) + to_chat(src, "You sense your form change as you are uploaded into [src].") + bot_name = name + name = paicard.pai.name + faction = user.faction + add_attack_logs(user, paicard.pai, "Uploaded to [src.bot_name]") + return + + if(istype(W, /obj/item/hemostat) && paicard) if(open) to_chat(user, "Close the access panel before manipulating the personality slot!") - else - to_chat(user, "You attempt to pull [paicard] free...") - if(do_after(user, 30 * W.toolspeed, target = src)) - if(paicard) - user.visible_message("[user] uses [W] to pull [paicard] out of [bot_name]!","You pull [paicard] out of [bot_name] with [W].") - ejectpai(user) - else - return ..() + return + + to_chat(user, "You attempt to pull [paicard] free...") + if(do_after(user, 30 * W.toolspeed, target = src)) + if(paicard) + user.visible_message("[user] uses [W] to pull [paicard] out of [bot_name]!","You pull [paicard] out of [bot_name] with [W].") + ejectpai(user) + return + return ..() /mob/living/simple_animal/bot/screwdriver_act(mob/living/user, obj/item/I) if(user.a_intent == INTENT_HARM) @@ -696,7 +710,6 @@ Pass a positive integer as an argument to override a bot's default speed. - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Patrol and summon code! //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1164,3 +1177,14 @@ Pass a positive integer as an argument to override a bot's default speed. data["emagged"] = emagged data["remote_disabled"] = remote_disabled return data + +// AI bot access verb TGUI +/mob/living/simple_animal/bot/proc/get_bot_data() + . = list( + "name" = name ? name : model, // name is the actual bot name. PAI may change it. Mulebot suffix system uses bot_name // WHY, WHO MADE THIS + "model" = model, // + "status" = mode, // BOT_IDLE is 0, using mode_name will bsod tgui + "location" = get_area(src), + "on" = on, + "UID" = UID(), + ) diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 0ecf75e9a7f..fa3ab06c3c7 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -81,6 +81,7 @@ target = null oldloc = null area_locked = null + update_icon() /mob/living/simple_animal/bot/cleanbot/set_custom_texts() text_hack = "You corrupt [name]'s cleaning software." @@ -173,6 +174,7 @@ oldloc = loc /mob/living/simple_animal/bot/cleanbot/proc/assign_area() + auto_patrol = FALSE // Don't want autopatrol if we are area locked if(area_locked) area_locked = null else diff --git a/code/modules/mob/living/simple_animal/bot/griefsky.dm b/code/modules/mob/living/simple_animal/bot/griefsky.dm index 37406b435e5..4b76c0696a4 100644 --- a/code/modules/mob/living/simple_animal/bot/griefsky.dm +++ b/code/modules/mob/living/simple_animal/bot/griefsky.dm @@ -7,7 +7,8 @@ maxHealth = 100 base_icon = "griefsky" window_name = "Automatic Security Unit v3.0" - + bot_type = GRIEF_BOT + model = "Griefsky" var/spin_icon = "griefsky-c" // griefsky and griefsky junior have dif icons var/weapon = /obj/item/melee/energy/sword/saber var/block_chance = 50 //block attacks diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/kangaroo.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/kangaroo.dm index 79e1145eee3..eafab412247 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/kangaroo.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/kangaroo.dm @@ -13,6 +13,7 @@ emote_hear = list("bark") maxHealth = 150 health = 150 + butcher_results = list(/obj/item/food/snacks/meat/kangaroo = 6) harm_intent_damage = 3 melee_damage_lower = 5 // avg damage 12.5 without kick, (12.5+12.5+60)/3=25 with kick melee_damage_upper = 20 diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 7035e9cf2d6..3e6fa6919be 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -660,6 +660,42 @@ header = "


" info = "" +/obj/item/paper/nuclear_guide_operating + name = "nuclear guide : 'Operating the Nuclear Device'" + info = "ARMING THE NUCLEAR DEVICE
\ + 1. Insert the NAD.
\ + 2. Enter the code provided by Central Command. For this training device, the code is 11111.
\ + 3. (Optional) Set a specific timer for detonation. Default and minimum is 2 minutes.
\ + 4. Disable the safety.
\ + 5. Arm the nuclear device.
\ + 6. Take out the NAD to ensure the device stays armed.
\ + DISARMING THE NUCLEAR DEVICE
\ + Follow step 1 and 2, then hit the disarm. If you have the NAD but don't know the code, refer to the Defusing guide. If you have neither, refer to the Spacing guide." + +/obj/item/paper/nuclear_guide_defusing + name = "nuclear guide : 'Defusing the Nuclear Device'" + info = "DEFUSING THE NUCLEAR DEVICE
\ + IF YOU DON'T HAVE THE NAD : Refer to the Spacing guide, you cannot defuse the nuclear device.
\ + 1. Insert the NAD.
\ + 2. Use a SCREWDRIVER and open the device's panel.
\ + 3. CUT the CONTROL wire using WIRECUTTERS to short out the control panel and bypass it.
\ + 4. PULSE the DISARM wire using a MULTITOOL to stop the bomb's timer.
\ + WARNING : Nuclear devices deployed by hostile operatives will likely have unlabelled wires.
\ + PULSING or CUTTING the DETONATOR wire will prematurely detonate the bomb if the timer is active.
\ + Depending on the timer left on the bomb, try your luck or refer to the Spacing guide." + +/obj/item/paper/nuclear_guide_spacing + name = "nuclear guide : 'Spacing the Nuclear Device'" + info = "SPACING THE NUCLEAR DEVICE
\ + To be used on assets of hostile operatives only. Any loss of NT nuclear devices following this guide will be charged as Grand Theft per Space Law.
\ + 1. Ensure the device's access panel is closed. Use a screwdriver to close it if it isn't.
\ + 2. Use a WELDING TOOL to cut the anchoring bolt covers.
\ + 3. Use a CROWBAR to pry the bolts open.
\ + 4. Use a WELDING TOOL to cut the anchoring system sealant.
\ + 5. Use a WRENCH to unwrench the anchoring bolts.
\ + 6. Use a CROWBAR to pry the nuclear device off its anchors.
\ + 7. DRAG the nuclear device to the closest opening to SPACE, and PUSH it away from the station." + /obj/item/paper/central_command name = "paper" header ="


Nanotrasen Central Command

Official Expedited Memorandum


" diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm index 231dafbef73..e21c00727b2 100644 --- a/code/modules/pda/PDA.dm +++ b/code/modules/pda/PDA.dm @@ -312,9 +312,6 @@ GLOBAL_LIST_EMPTY(PDAs) add_pen(C) to_chat(user, "You slide \the [C] into \the [src].") playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE) - else if(istype(C, /obj/item/nanomob_card)) - if(cartridge && istype(cartridge, /obj/item/cartridge/mob_hunt_game)) - cartridge.attackby(C, user, params) /obj/item/pda/proc/add_pen(obj/item/P) P.forceMove(src) diff --git a/code/modules/pda/cart.dm b/code/modules/pda/cart.dm index 4a66081f956..75deb8f685d 100644 --- a/code/modules/pda/cart.dm +++ b/code/modules/pda/cart.dm @@ -306,40 +306,3 @@ messenger_plugins = list( new /datum/data/pda/messenger_plugin/virus/frame ) - -/obj/item/cartridge/mob_hunt_game - name = "Nano-Mob Hunter GO! Cartridge" - desc = "The hit new PDA game that lets you track down and capture your favorite Nano-Mobs living in your world!" - icon_state = "cart-eye" - programs = list( - new /datum/data/pda/app/mob_hunter_game - ) - -/obj/item/cartridge/mob_hunt_game/examine(mob/user) - . = ..() - if(emagged) - if(isAntag(user)) - . += "This copy of Nano-Mob Hunter GO! has been hacked to allow the creation of trap mobs which will cause any PDA that attempts to capture it to shock anyone holding it. Hacked copies of the game will not trigger the trap. Provided you actually find someone playing nanomobs, that is." - -/obj/item/cartridge/mob_hunt_game/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/nanomob_card)) - var/obj/item/nanomob_card/card = O - var/datum/data/pda/app/mob_hunter_game/my_game = programs[1] - - if(my_game.register_capture(card.mob_data)) - to_chat(user, "Transfer successful!") - qdel(card) - else - to_chat(user, "Transfer failed. Could not read mob data from card.") - - else - ..() - -/obj/item/cartridge/mob_hunt_game/emag_act(mob/user) - if(!emagged) - emagged = TRUE - var/datum/data/pda/app/mob_hunter_game/my_game = programs[1] - my_game.hacked = TRUE - to_chat(user, "TR4P_M45T3R.mod successfully initialized. ToS violated. User Agreement nullified. Gotta pwn them all.") - to_chat(user, "You can now create trapped versions of any mob in your collection that will damage hunters who attempt to capture it.") - return TRUE diff --git a/code/modules/pda/mob_hunt_game_app.dm b/code/modules/pda/mob_hunt_game_app.dm deleted file mode 100644 index 73eab8cf1a5..00000000000 --- a/code/modules/pda/mob_hunt_game_app.dm +++ /dev/null @@ -1,205 +0,0 @@ - -/* - This stuff isn't included with in core_apps.dm because it is so distinct and would end up making the file huge (more than it already is). - I put it in it's own file in order to help it stay organized and easier to locate the procs and such. - For reference, the other Nano-mob Hunter GO files are in /code/game/modules/arcade/mob_hunt -*/ - -/datum/data/pda/app/mob_hunter_game - name = "Nano-Mob Hunter GO" - icon = "gamepad" - template = "pda_mob_hunt" - category = "Games" - - var/list/my_collection = list() - var/current_index = 0 - var/connected = FALSE - var/hacked = FALSE //if set, this cartridge is able to spawn trap mobs from its collection (set via emag_act on the cartridge) - var/catch_mod = 0 //used to adjust the likelihood of a mob running from this client, a negative value means it is less likely to run (support for temporary bonuses) - var/wild_captures = 0 //used to track the total number of mobs captured from the wild (does not count card mobs) by this client - var/scan_range = 3 //maximum distance (in tiles) from which the client can reveal nearby mobs - -/datum/data/pda/app/mob_hunter_game/start() - ..() - START_PROCESSING(SSobj, pda) - -/datum/data/pda/app/mob_hunter_game/stop() - ..() - disconnect("Program Terminated") - STOP_PROCESSING(SSobj, pda) - -/datum/data/pda/app/mob_hunter_game/Destroy() - if(pda) - STOP_PROCESSING(SSobj, pda) - SSmob_hunt.connected_clients -= src - return ..() - -/datum/data/pda/app/mob_hunter_game/proc/scan_nearby() - if(!SSmob_hunt || !connected) - return - for(var/turf/T in range(scan_range, get_turf(pda))) - for(var/obj/effect/nanomob/N in T.contents) - if(src in N.clients_encountered) - //hide the mob - N.conceal() - else - //reveal the mob - N.reveal() - -/datum/data/pda/app/mob_hunter_game/proc/reconnect() - if(!SSmob_hunt || !SSmob_hunt.server_status || connected) - //show a message about the server being unavailable (because it doesn't exist / didn't get set to the global var / is offline) - return 0 - SSmob_hunt.connected_clients += src - connected = TRUE - if(pda) - pda.atom_say("Connection established. Capture all of the mobs, [pda.owner ? pda.owner : "hunter"]!") - return 1 - -/datum/data/pda/app/mob_hunter_game/proc/get_player() - if(!pda) - return null - if(ishuman(pda.loc)) - var/mob/living/carbon/human/H = pda.loc - return H - return null - -/datum/data/pda/app/mob_hunter_game/proc/disconnect(reason = null) - if(!SSmob_hunt || !connected) - return - SSmob_hunt.connected_clients -= src - for(var/obj/effect/nanomob/N in (SSmob_hunt.normal_spawns + SSmob_hunt.trap_spawns)) - N.conceal(list(get_player())) - connected = FALSE - //show a disconnect message if we were disconnected involuntarily (reason argument provided) - if(pda && reason) - pda.atom_say("Disconnected from server. Reason: [reason].") - -/datum/data/pda/app/mob_hunter_game/program_process() - if(!SSmob_hunt || !connected) - return - scan_nearby() - -/datum/data/pda/app/mob_hunter_game/proc/register_capture(datum/mob_hunt/captured, wild = FALSE) - if(!captured) - return FALSE - my_collection += captured - RegisterSignal(captured, COMSIG_PARENT_QDELETING, PROC_REF(remove_mob)) - if(wild) - wild_captures++ - return TRUE - -/datum/data/pda/app/mob_hunter_game/update_ui(mob/user, list/data) - if(!SSmob_hunt || !(src in SSmob_hunt.connected_clients)) - data["connected"] = 0 - else - data["connected"] = 1 - data["wild_captures"] = wild_captures - data["no_collection"] = 0 - if(!length(my_collection)) - data["no_collection"] = 1 - return - var/datum/mob_hunt/mob_info - if(!current_index) - current_index = 1 - if(current_index > length(my_collection)) - current_index = 1 - if(current_index < 1) - current_index = length(my_collection) - mob_info = my_collection[current_index] - var/list/entry = list( - "nickname" = mob_info.nickname, - "real_name" = mob_info.mob_name, - "level" = mob_info.level, - "type1" = mob_info.get_type1(), - "type2" = mob_info.get_type2(), - "sprite" = "[mob_info.icon_state_normal].png", - "is_hacked" = hacked - ) - if(mob_info.is_shiny) - entry["sprite"] = "[mob_info.icon_state_shiny].png" - data["entry"] = entry - -/datum/data/pda/app/mob_hunter_game/proc/assign_nickname() - if(!length(my_collection)) - return - var/datum/mob_hunt/mob_info = my_collection[current_index] - var/old_name = mob_info.mob_name - if(mob_info.nickname) - old_name = mob_info.nickname - mob_info.nickname = tgui_input_text(usr, "Give a nickname to [old_name]?", "Nickname", old_name) - -/datum/data/pda/app/mob_hunter_game/proc/release() - if(!length(my_collection)) - return - if(tgui_alert(usr, "Are you sure you want to release this mob back into the wild?", "Confirm Release", list("Yes", "No")) == "Yes") - remove_mob() - -/datum/data/pda/app/mob_hunter_game/proc/print_card() - if(!pda || !length(my_collection)) - return - var/obj/item/nanomob_card/card = new/obj/item/nanomob_card(null) - var/datum/mob_hunt/mob_info = my_collection[current_index] - card.mob_data = mob_info - card.update_info() - card.forceMove(get_turf(pda)) - remove_mob() - -/** - * Removes a Nanomob from the [my_collection] list. - * - * The Nanomob that is currently selected in the app ([current_index]) will be removed from the list unless a `mob_override` argument is given, in which case that will be removed instead. - * - * Arguments: - * * mob_override - A specific Nanomob to remove from the list. (Optional) - */ -/datum/data/pda/app/mob_hunter_game/proc/remove_mob(datum/mob_hunt/mob_override = null) - SIGNAL_HANDLER - if(!length(my_collection)) - return - - if(mob_override) - my_collection -= mob_override - else - my_collection -= my_collection[current_index] - - var/collection_length = length(my_collection) - if(current_index > collection_length) - current_index = collection_length - -/datum/data/pda/app/mob_hunter_game/proc/set_trap() - if(!length(my_collection) || !pda || !hacked) - return - var/datum/mob_hunt/bait = my_collection[current_index] - bait = bait.type - new bait(1, get_turf(pda)) - -/datum/data/pda/app/mob_hunter_game/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - if(..()) - return - - if(!pda.silent) - playsound(pda, 'sound/machines/terminal_select.ogg', 15, TRUE) - - . = TRUE - switch(action) - if("Rename") - assign_nickname() - if("Release") - release() - if("Next") - current_index++ - if(current_index > length(my_collection)) - current_index = 1 - if("Prev") - current_index-- - if(current_index < 1) - current_index = length(my_collection) - if("Reconnect") - reconnect() - if("Disconnect") - disconnect() - if("Transfer") - print_card() - if("Set_Trap") - set_trap() diff --git a/code/modules/pda/pda_tgui.dm b/code/modules/pda/pda_tgui.dm index 27310410d31..96c1a8f5296 100644 --- a/code/modules/pda/pda_tgui.dm +++ b/code/modules/pda/pda_tgui.dm @@ -60,11 +60,6 @@ return data -/obj/item/pda/ui_assets(mob/user) - return list( - get_asset_datum(/datum/asset/simple/mob_hunt) - ) - // Yes the stupid amount of args here is important, see L102 /obj/item/pda/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) diff --git a/code/modules/power/engines/singularity/singularity.dm b/code/modules/power/engines/singularity/singularity.dm index b00a030a16e..de8de552f88 100644 --- a/code/modules/power/engines/singularity/singularity.dm +++ b/code/modules/power/engines/singularity/singularity.dm @@ -21,15 +21,20 @@ move_resist = INFINITY //no, you don't get to push the singulo. Not even you OP wizard gateway statues var/consume_range = 0 //How many tiles out do we eat var/event_chance = 15 //Prob for event each tick - var/target = null //its target. moves towards the target if it has one var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing var/last_warning var/consumedSupermatter = FALSE //If the singularity has eaten a supermatter shard and can go to stage six var/warps_projectiles = TRUE var/obj/effect/warp_effect/supermatter/warp resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + /// The target of the singularity. It will wander slowly towards this, and pick another target once it reaches it. + var/target = null + /// If there is a syndicate beacon, the singularity will move quickly towards it. + var/beacon_target = null /// Whether or not we've pinged ghosts var/isnt_shutting_down = FALSE + /// Init list that has all the areas that we can possibly move to, to reduce processing impact + var/list/all_possible_areas = list() /obj/singularity/Initialize(mapload, starting_energy = 50) . = ..() @@ -45,8 +50,9 @@ GLOB.singularities += src for(var/obj/machinery/power/singularity_beacon/singubeacon in GLOB.machines) if(singubeacon.active) - target = singubeacon + beacon_target = singubeacon break + all_possible_areas = findUnrestrictedEventArea() /obj/singularity/Destroy() STOP_PROCESSING(SSobj, src) @@ -323,6 +329,10 @@ return +/obj/singularity/proc/assign_target() + var/area/where_to_move = pick(all_possible_areas) // Grabs a random area that isn't restricted + var/turf/target_area_turfs = get_area_turfs(where_to_move) // Grabs the turfs from said area + target = pick(target_area_turfs) // Grabs a single turf from the entire list /obj/singularity/proc/move(force_move = 0) if(!move_self) @@ -330,11 +340,14 @@ var/movement_dir = pick(GLOB.alldirs - last_failed_movement) + if(get_turf(src) == target || !target) + assign_target() if(force_move) movement_dir = force_move - - if(target && prob(60)) - movement_dir = get_dir(src,target) //moves to a singulo beacon, if there is one + if(target && prob(20)) + movement_dir = get_dir(src, target) //moves to a random spot on the map + if(beacon_target && prob(60)) + movement_dir = get_dir(src, target) //moves to a singulo beacon, if there is one step(src, movement_dir) diff --git a/code/modules/power/engines/supermatter/supermatter.dm b/code/modules/power/engines/supermatter/supermatter.dm index 97b41d4c8ed..bac8aceb3b2 100644 --- a/code/modules/power/engines/supermatter/supermatter.dm +++ b/code/modules/power/engines/supermatter/supermatter.dm @@ -353,7 +353,7 @@ explode() -/obj/machinery/atmospherics/supermatter_crystal/proc/explode() +/obj/machinery/atmospherics/supermatter_crystal/proc/explode(forced_combined_gas = 0, forced_power = 0, forced_gasmix_power_ratio = 0) SSblackbox.record_feedback("amount", "supermatter_delaminations", 1) for(var/mob in GLOB.alive_mob_list) var/mob/living/L = mob @@ -379,14 +379,14 @@ else to_chat(M, "You hold onto \the [M.loc] as hard as you can, as reality distorts around you. You feel safe.") - if(combined_gas > MOLE_CRUNCH_THRESHOLD) + if(max(combined_gas, forced_combined_gas) > MOLE_CRUNCH_THRESHOLD) investigate_log("has collapsed into a singularity.", "supermatter") if(T) var/obj/singularity/S = new(T) S.energy = 800 S.consume(src) return //No boom for me sir - else if(power > POWER_PENALTY_THRESHOLD) + else if(max(power, forced_power) > POWER_PENALTY_THRESHOLD) investigate_log("has spawned additional energy balls.", "supermatter") if(T) var/obj/singularity/energy_ball/E = new(T) @@ -396,6 +396,8 @@ // crystals.runEvent() // return //No boom for me sir //Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41 + if(forced_gasmix_power_ratio) + gasmix_power_ratio = forced_gasmix_power_ratio explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1) qdel(src) diff --git a/code/modules/power/engines/tesla/energy_ball.dm b/code/modules/power/engines/tesla/energy_ball.dm index 79274c66915..7e526501faf 100644 --- a/code/modules/power/engines/tesla/energy_ball.dm +++ b/code/modules/power/engines/tesla/energy_ball.dm @@ -39,8 +39,6 @@ var/movement_dir /// Variable that defines whether it has a field generator close enough var/has_close_field = FALSE - /// Init list that has all the areas that we can possibly move to, to reduce processing impact - var/list/all_possible_areas = list() /// How many tiles do we move per movement step? var/steps_per_move = 8 diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 7baf9bb6cc7..b4b071e6f61 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -67,22 +67,14 @@ var/flight_x_offset = 0 var/flight_y_offset = 0 - //Zooming - var/zoomable = FALSE //whether the gun generates a Zoom action on creation - var/zoomed = FALSE //Zoom toggle - var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect) - var/datum/action/toggle_scope_zoom/azoom - /obj/item/gun/Initialize(mapload) . = ..() - build_zooming() ADD_TRAIT(src, TRAIT_CAN_POINT_WITH, ROUNDSTART_TRAIT) appearance_flags |= KEEP_TOGETHER /obj/item/gun/Destroy() QDEL_NULL(bayonet) QDEL_NULL(chambered) - QDEL_NULL(azoom) QDEL_NULL(gun_light) return ..() @@ -154,6 +146,10 @@ /obj/item/gun/afterattack(atom/target, mob/living/user, flag, params) if(firing_burst) return + if(SEND_SIGNAL(src, COMSIG_GUN_TRY_FIRE, user, target, flag, params) & COMPONENT_CANCEL_GUN_FIRE) + return + if(SEND_SIGNAL(src, COMSIG_MOB_TRY_FIRE, user, target, flag, params) & COMPONENT_CANCEL_GUN_FIRE) + return if(flag) //It's adjacent, is the user, or is on the user's person if(target in user.contents) //can't shoot stuff inside us. return @@ -414,11 +410,6 @@ visible_message("[src]'s light fades and turns off.") -/obj/item/gun/dropped(mob/user) - ..() - zoom(user,FALSE) - if(azoom) - azoom.Remove(user) /obj/item/gun/AltClick(mob/user) ..() @@ -485,93 +476,8 @@ process_fire(target, user, 1, params) -///////////// -// ZOOMING // -///////////// +/obj/item/gun/proc/on_scope_success() + return -/datum/action/toggle_scope_zoom - name = "Toggle Scope" - check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING - button_icon_state = "sniper_zoom" - var/obj/item/gun/gun = null - -/datum/action/toggle_scope_zoom/Destroy() - gun = null - return ..() - -/datum/action/toggle_scope_zoom/Trigger(left_click) - gun.zoom(owner) - -/datum/action/toggle_scope_zoom/IsAvailable() - . = ..() - if(!. && gun) - gun.zoom(owner, FALSE) - -/datum/action/toggle_scope_zoom/Remove(mob/living/L) - gun.zoom(L, FALSE) - ..() - -/obj/item/gun/proc/zoom(mob/living/user, forced_zoom) - if(!user || !user.client) - return - - switch(forced_zoom) - if(FALSE) - zoomed = FALSE - if(TRUE) - zoomed = TRUE - else - zoomed = !zoomed - - if(zoomed) - var/_x = 0 - var/_y = 0 - switch(user.dir) - if(NORTH) - _y = zoom_amt - if(EAST) - _x = zoom_amt - if(SOUTH) - _y = -zoom_amt - if(WEST) - _x = -zoom_amt - - user.client.pixel_x = world.icon_size*_x - user.client.pixel_y = world.icon_size*_y - else - user.client.pixel_x = 0 - user.client.pixel_y = 0 - - -//Proc, so that gun accessories/scopes/etc. can easily add zooming. -/obj/item/gun/proc/build_zooming() - if(azoom) - return - - if(zoomable) - azoom = new() - azoom.gun = src - RegisterSignal(src, COMSIG_ITEM_EQUIPPED, PROC_REF(ZoomGrantCheck)) - -/** - * Proc which will be called when the gun receives the `COMSIG_ITEM_EQUIPPED` signal. - * - * This happens if the mob picks up the gun, or equips it to any of their slots. - * If the slot is anything other than either of their hands (such as the back slot), un-zoom them, and `Remove` the zoom action button from the mob. - * Otherwise, `Grant` the mob the zoom action button. - * - * Arguments: - * * source - the gun that got equipped, which is `src`. - * * user - the mob equipping the gun. - * * slot - the slot the gun is getting equipped to. - */ -/obj/item/gun/proc/ZoomGrantCheck(datum/source, mob/user, slot) - // Checks if the gun got equipped into either of the user's hands. - if(slot != SLOT_HUD_RIGHT_HAND && slot != SLOT_HUD_LEFT_HAND) - // If its not in their hands, un-zoom, and remove the zoom action button. - zoom(user, FALSE) - azoom.Remove(user) - return FALSE - - // The gun is equipped in their hands, give them the zoom ability. - azoom.Grant(user) +/obj/item/gun/proc/on_scope_end() + return diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 9bc6e43ec82..4c2220793e6 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -1,6 +1,6 @@ /obj/item/gun/energy/kinetic_accelerator name = "proto-kinetic accelerator" - desc = "A self recharging, ranged mining tool that does increased damage in low pressure. Capable of holding up to six slots worth of mod kits." + desc = "A self-recharging, ranged mining tool that does increased damage in low pressure environments. It can be upgraded using specialised mod kits." icon_state = "kineticgun" item_state = "kineticgun" ammo_type = list(/obj/item/ammo_casing/energy/kinetic) @@ -34,6 +34,7 @@ for(var/A in get_modkits()) var/obj/item/borg/upgrade/modkit/M = A . += "There is a [M.name] mod installed, using [M.cost]% capacity." + . += "You can use a crowbar on it to remove it's installed mod kits." /obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/borg/upgrade/modkit) && max_mod_capacity) @@ -438,7 +439,7 @@ /obj/item/borg/upgrade/modkit/aoe/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA) if(stats_stolen) return - new /obj/effect/temp_visual/explosion/fast(target_turf) + new /obj/effect/temp_visual/pka_explosion(target_turf) if(turf_aoe) for(var/T in RANGE_TURFS(1, target_turf) - target_turf) if(ismineralturf(T) && !is_ancient_rock(T)) diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 3d194b08510..fddd8eacaf4 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -126,39 +126,21 @@ weapon_weight = WEAPON_HEAVY origin_tech = "combat=6;magnets=6;powerstorage=4" ammo_type = list(/obj/item/ammo_casing/energy/laser/sniper, /obj/item/ammo_casing/energy/laser/sniper/pierce) - zoomable = TRUE - zoom_amt = 7 shaded_charge = TRUE - /// Is the scope fully online or not? - var/scope_active = FALSE - var/stored_dir execution_speed = 8 SECONDS -/obj/item/gun/energy/lwap/zoom(mob/living/user, forced_zoom) +/obj/item/gun/energy/lwap/Initialize(mapload) . = ..() - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - stored_dir = H.dir - if(scope_active && !zoomed) - select_fire(H) - H.remove_status_effect(STATUS_EFFECT_LWAPSCOPE) - scope_active = FALSE - return - if(zoomed && do_after(user, 3 SECONDS, target = src)) - if(zoomed && !scope_active) //We check after to be sure. - scope_active = TRUE - to_chat(user, "SCOPE_CREEPER_[rand(1, 9999)] Online.") - select_fire(H) - H.apply_status_effect(STATUS_EFFECT_LWAPSCOPE, stored_dir) - return - if(zoomed) - zoom(user, FALSE) //Moved while scope was booting, so we unzoom + AddComponent(/datum/component/scope, range_modifier = 2, time_to_scope = 3 SECONDS, movement_cancels_scope = TRUE) -/obj/item/gun/energy/lwap/on_mob_move(dir, mob/user) - if(scope_active) - to_chat(user, "[src]'s scope is overloaded by movement and shuts down!") - zoom(user, FALSE) +/obj/item/gun/energy/lwap/on_scope_success(mob/living/user) + to_chat(user, "SCOPE_CREEPER_[rand(1, 9999)] Online.") + select_fire(user) + user.apply_status_effect(STATUS_EFFECT_LWAPSCOPE) + +/obj/item/gun/energy/lwap/on_scope_end(mob/living/user) + select_fire(user) + user.remove_status_effect(STATUS_EFFECT_LWAPSCOPE) /obj/item/gun/energy/lwap/attack_self() return //no manual ammo changing. @@ -273,7 +255,7 @@ return /// Special version given by the Safety Override upgrade and as a standard module for ERT engiborgs. -/obj/item/gun/energy/emitter/cyborg/proto +/obj/item/gun/energy/emitter/cyborg/proto name = "mobile proto-emitter" desc = "An emitter removed from its base and attached to a laser cannon frame. This one operates on unoptimised software, reducing its effectiveness." ammo_type = list(/obj/item/ammo_casing/energy/emitter/cyborg/proto) diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 1b299dd77fc..77f5b742d2c 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -74,11 +74,13 @@ weapon_weight = WEAPON_HEAVY w_class = WEIGHT_CLASS_BULKY ammo_type = list(/obj/item/ammo_casing/energy/disabler/smg) - burst_size = 2 - fire_delay = 2.5 shaded_charge = TRUE can_holster = FALSE +/obj/item/gun/energy/disabler/smg/Initialize(mapload) + . = ..() + AddComponent(/datum/component/automatic_fire, 0.15 SECONDS, allow_akimbo = FALSE) + /obj/item/gun/energy/disabler/cyborg name = "cyborg disabler" desc = "An integrated disabler that draws from a cyborg's power cell. This weapon contains a limiter to prevent the cyborg's power cell from overheating." diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index d9879a9f46e..c1d5716c536 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -332,10 +332,15 @@ fire_sound = 'sound/weapons/gunshots/gunshot_lascarbine.ogg' magin_sound = 'sound/weapons/gun_interactions/batrifle_magin.ogg' magout_sound = 'sound/weapons/gun_interactions/batrifle_magout.ogg' + actions_types = list() can_suppress = FALSE - burst_size = 2 + burst_size = 1 execution_speed = 5 SECONDS +/obj/item/gun/projectile/automatic/lasercarbine/Initialize(mapload) + . = ..() + AddComponent(/datum/component/automatic_fire, 0.15 SECONDS, allow_akimbo = FALSE) + /obj/item/gun/projectile/automatic/lasercarbine/update_icon_state() icon_state = "lasercarbine[magazine ? "-[CEILING(get_ammo(0)/5, 1)*5]" : ""]" item_state = "lasercarbine[magazine ? "-[CEILING(get_ammo(0)/5, 1)*5]" : ""]" diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm index 9c50158c7b0..587e65bf083 100644 --- a/code/modules/projectiles/guns/projectile/saw.dm +++ b/code/modules/projectiles/guns/projectile/saw.dm @@ -12,9 +12,14 @@ magin_sound = 'sound/weapons/gun_interactions/lmg_magin.ogg' magout_sound = 'sound/weapons/gun_interactions/lmg_magout.ogg' var/cover_open = FALSE + actions_types = list() can_suppress = FALSE - burst_size = 3 - fire_delay = 1 + burst_size = 1 + spread = 7 + +/obj/item/gun/projectile/automatic/l6_saw/Initialize(mapload) + . = ..() + AddComponent(/datum/component/automatic_fire, 0.2 SECONDS) /obj/item/gun/projectile/automatic/l6_saw/attack_self(mob/user) cover_open = !cover_open diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index 43781e87570..f8d317464e0 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -15,14 +15,18 @@ can_unsuppress = TRUE can_suppress = TRUE w_class = WEIGHT_CLASS_NORMAL - zoomable = TRUE - zoom_amt = 7 //Long range, enough to see in front of you, but no tiles behind you. slot_flags = SLOT_FLAG_BACK actions_types = list() execution_speed = 8 SECONDS + var/zoomable = TRUE + +/obj/item/gun/projectile/automatic/sniper_rifle/Initialize(mapload) + . = ..() + if(zoomable) + AddComponent(/datum/component/scope, range_modifier = 2) /obj/item/gun/projectile/automatic/sniper_rifle/process_fire(atom/target, mob/living/user, message = TRUE, params, zone_override, bonus_spread = 0) - if(istype(chambered.BB, /obj/item/projectile/bullet/sniper) && !zoomed) + if(istype(chambered.BB, /obj/item/projectile/bullet/sniper) && !HAS_TRAIT(user, TRAIT_SCOPED)) var/obj/item/projectile/bullet/sniper/S = chambered.BB if(S.non_zoom_spread) to_chat(user, "[src] must be zoomed in to fire this ammunition accurately!") diff --git a/code/modules/projectiles/guns/rocket.dm b/code/modules/projectiles/guns/rocket.dm index 1a6755a59e2..1e3f111479c 100644 --- a/code/modules/projectiles/guns/rocket.dm +++ b/code/modules/projectiles/guns/rocket.dm @@ -13,11 +13,14 @@ fire_sound = 'sound/weapons/blastcannon.ogg' fire_delay = 40 recoil = 2 - zoomable = TRUE - zoom_amt = 7 var/missile_speed = 2 var/missile_range = 30 + +/obj/item/gun/rocketlauncher/Initialize(mapload) + . = ..() + AddComponent(/datum/component/scope, range_modifier = 2) + /obj/item/gun/rocketlauncher/examine(mob/user) . = ..() . += "It is currently [chambered ? "" : "un"]loaded." diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 1c07afabb50..b62eb64b0f6 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -163,9 +163,11 @@ B.reagents.add_reagent("vaccine", 15, list(vaccine_type)) if("eject_beaker") eject_beaker() + update_static_data(ui.user) if("destroy_eject_beaker") beaker.reagents.clear_reagents() eject_beaker() + update_static_data(ui.user) if("print_release_forms") var/strain_index = text2num(params["strain_index"]) if(isnull(strain_index)) @@ -202,6 +204,7 @@ A.AssignName(new_name) for(var/datum/disease/advance/AD in GLOB.active_diseases) AD.Refresh() + update_static_data(ui.user) if("switch_strain") var/strain_index = text2num(params["strain_index"]) if(isnull(strain_index) || strain_index < 1) diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 09ed6ed24ef..645ed9f0524 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -21,7 +21,7 @@ /obj/item/stack/sheet/metal = list("iron" = 20), /obj/item/stack/rods = list("iron" = 10), /obj/item/stack/sheet/plasteel = list("iron" = 20, "plasma_dust" = 20), - /obj/item/stack/sheet/wood = list("carbon" = 20), + /obj/item/stack/sheet/wood = list("carbon" = 4), /obj/item/stack/sheet/glass = list("silicon" = 20), /obj/item/stack/sheet/rglass = list("silicon" = 20, "iron" = 20), /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20), @@ -30,10 +30,6 @@ /obj/item/stack/sheet/mineral/silver = list("silver" = 20), /obj/item/stack/sheet/mineral/gold = list("gold" = 20), - /obj/item/grown/nettle/basic = list("wasabi" = 0), - /obj/item/grown/nettle/death = list("facid" = 0, "sacid" = 0), - /obj/item/grown/novaflower = list("capsaicin" = 0, "condensedcapsaicin" = 0), - // Blender Stuff /obj/item/food/snacks/grown/tomato = list("ketchup" = 0), /obj/item/food/snacks/grown/wheat = list("flour" = -5), @@ -56,7 +52,8 @@ /obj/item/food = list(), /obj/item/reagent_containers/pill = list(), /obj/item/reagent_containers/patch = list(), - /obj/item/clothing/mask/cigarette = list() + /obj/item/clothing/mask/cigarette = list(), + /obj/item/grown = list() ) var/list/juice_items = list ( @@ -439,21 +436,54 @@ var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume var/amount = special_blend[r_id] - if(amount <= 0) - if(amount == 0) - if(O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment") * efficiency, space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - if(O.reagents.has_reagent("plantmatter")) - beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("plantmatter") * efficiency, space)) - O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) - else - if(O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment") * abs(amount) * efficiency), space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - if(O.reagents.has_reagent("plantmatter")) - beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("plantmatter") * abs(amount) * efficiency), space)) - O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) + + if(amount == 0) + if(O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment") * efficiency, space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + if(O.reagents.has_reagent("plantmatter")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("plantmatter") * efficiency, space)) + O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) + else if(amount < 0) + if(O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment") * abs(amount) * efficiency), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + if(O.reagents.has_reagent("plantmatter")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("plantmatter") * abs(amount) * efficiency), space)) + O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) + else + O.reagents.trans_id_to(beaker, r_id, min(amount, space)) + + if(beaker.reagents.holder_full()) + break + + O.reagents.trans_to(beaker, O.reagents.total_volume) + + if(!O.reagents.total_volume) + remove_object(O) + if(beaker.reagents.holder_full()) + return + // Inedible Plants + for(var/obj/item/grown/O in holdingitems) + var/list/special_blend = get_special_blend(O) + for(var/r_id in special_blend) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = special_blend[r_id] + + if(amount == 0) + if(O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment") * efficiency, space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + if(O.reagents.has_reagent("plantmatter")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("plantmatter") * efficiency, space)) + O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) + else if(amount < 0) + if(O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment") * abs(amount) * efficiency), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + if(O.reagents.has_reagent("plantmatter")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("plantmatter") * abs(amount) * efficiency), space)) + O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space)) else O.reagents.trans_id_to(beaker, r_id, min(amount, space)) @@ -488,26 +518,6 @@ if(beaker.reagents.holder_full()) return - // Plants - for(var/obj/item/grown/O in holdingitems) - var/list/special_blend = get_special_blend(O) - for(var/r_id in special_blend) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = special_blend[r_id] - - if(amount == 0) - if(O.reagents.has_reagent(r_id)) - beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount(r_id) * efficiency, space)) - else - beaker.reagents.add_reagent(r_id, min(amount * efficiency, space)) - - if(beaker.reagents.holder_full()) - break - - remove_object(O) - if(beaker.reagents.holder_full()) - return - // Slime Extracts for(var/obj/item/slime_extract/O in holdingitems) var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm index f5fc09e778d..fa8761a520a 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol.dm @@ -163,7 +163,7 @@ drink_name = "Glass of Mojito" drink_desc = "Fresh from Spesscuba." taste_description = "mojito" - goal_difficulty = REAGENT_GOAL_EASY + goal_difficulty = REAGENT_GOAL_NORMAL /datum/reagent/consumable/ethanol/vodka name = "Vodka" @@ -776,7 +776,7 @@ drink_name = "Demons Blood" drink_desc = "Just looking at this thing makes the hair at the back of your neck stand up." taste_description = "evil" - goal_difficulty = REAGENT_GOAL_EASY + goal_difficulty = REAGENT_GOAL_HARD /datum/reagent/consumable/ethanol/vodkatonic name = "Vodka and Tonic" @@ -1529,7 +1529,7 @@ drink_desc = "A sawed-off cola bottle filled with Fernet Cola. You can hear cuarteto music coming from the inside." taste_description = "low class heaven" remove_nutrition = 1 - goal_difficulty = REAGENT_GOAL_EASY + goal_difficulty = REAGENT_GOAL_EXCESSIVE /datum/reagent/consumable/ethanol/gimlet name = "Gimlet" @@ -1553,7 +1553,7 @@ drink_name = "Sidecar" drink_desc = "You can smell the citrus from here!" taste_description = "smooth cognac and tart citrus" - goal_difficulty = REAGENT_GOAL_HARD + goal_difficulty = REAGENT_GOAL_EASY /datum/reagent/consumable/ethanol/whiskey_sour name = "Whiskey Sour" @@ -1577,7 +1577,7 @@ drink_name = "Mint Julep" drink_desc = "A dainty glass of whiskey and mint on the rocks. Perfect for summer!" taste_description = "sweet and cooling mint" - goal_difficulty = REAGENT_GOAL_EASY + goal_difficulty = REAGENT_GOAL_NORMAL /datum/reagent/consumable/ethanol/pina_colada name = "Pina Colada" diff --git a/code/modules/reagents/chemistry/reagents/drugs.dm b/code/modules/reagents/chemistry/reagents/drugs.dm index ee4a091a22f..cf4d29a17c3 100644 --- a/code/modules/reagents/chemistry/reagents/drugs.dm +++ b/code/modules/reagents/chemistry/reagents/drugs.dm @@ -453,7 +453,7 @@ taste_description = "WAAAAGH" var/bonus_damage = 2 goal_department = "Science" - goal_difficulty = REAGENT_GOAL_HARD + goal_difficulty = REAGENT_GOAL_EXCESSIVE /datum/reagent/bath_salts/on_mob_add(mob/living/L) if(ishuman(L)) diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index 0c1b82d9d0c..eac48e6f390 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -1508,7 +1508,8 @@ metabolization_rate = 0.5 harmless = FALSE taste_description = "2 minutes of suffering" - var/list/stimulant_list = list("methamphetamine", "crank", "bath_salts", "stimulative_agent", "stimulants", "mephedrone") + process_flags = ORGANIC | SYNTHETIC + var/list/stimulant_list = list("methamphetamine", "crank", "bath_salts", "stimulative_agent", "stimulants", "mephedrone", "ultralube", "surge", "surge_plus", "combatlube") /datum/reagent/medicine/nanocalcium/on_mob_life(mob/living/carbon/human/M) var/update_flags = STATUS_UPDATE_NONE @@ -1521,7 +1522,7 @@ if(1 to 19) M.AdjustJitter(8 SECONDS) if(prob(10)) - to_chat(M, "Your skin feels hot and your veins are on fire!") + to_chat(M, "You feel great pain from the nanomachines inside you!") update_flags |= M.adjustFireLoss(1 * REAGENTS_EFFECT_MULTIPLIER, FALSE) for(var/datum/reagent/R in M.reagents.reagent_list) if(stimulant_list.Find(R.id)) @@ -1549,7 +1550,10 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M for(var/obj/item/organ/internal/I in M.internal_organs) // 60 healing to all internal organs. - I.heal_internal_damage(4) + I.heal_internal_damage(4, TRUE) + if(istype(I, /obj/item/organ/internal/cyberimp)) // Fix disabled implants like the ipc charging implant + var/obj/item/organ/internal/cyberimp/crit = I + crit.crit_fail = FALSE if(H.blood_volume < BLOOD_VOLUME_NORMAL * 0.7)// If below 70% blood, regenerate 150 units total H.blood_volume += 10 for(var/datum/disease/critical/heart_failure/HF in H.viruses) @@ -1559,8 +1563,8 @@ if(M.health < 40) update_flags |= M.adjustOxyLoss(-5 * REAGENTS_EFFECT_MULTIPLIER, FALSE) update_flags |= M.adjustToxLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE) - update_flags |= M.adjustBruteLoss(-3 * REAGENTS_EFFECT_MULTIPLIER, FALSE) - update_flags |= M.adjustFireLoss(-3 * REAGENTS_EFFECT_MULTIPLIER, FALSE) + update_flags |= M.adjustBruteLoss(-3 * REAGENTS_EFFECT_MULTIPLIER, FALSE, robotic = TRUE) + update_flags |= M.adjustFireLoss(-3 * REAGENTS_EFFECT_MULTIPLIER, FALSE, robotic = TRUE) else if(prob(25)) to_chat(M, "Your skin feels like it is ripping apart and your veins are on fire!") //It is experimental and does cause scars, after all. diff --git a/code/modules/reagents/chemistry/reagents_holder.dm b/code/modules/reagents/chemistry/reagents_holder.dm index 413b54262be..a1319d355e8 100644 --- a/code/modules/reagents/chemistry/reagents_holder.dm +++ b/code/modules/reagents/chemistry/reagents_holder.dm @@ -810,6 +810,15 @@ /datum/reagents/proc/get_reagent(type) . = locate(type) in reagent_list +/datum/reagents/proc/get_reagent_by_id(id) + var/list/cached_reagents = reagent_list + for(var/A in cached_reagents) + var/datum/reagent/R = A + if(R.id == id) + return R + + return + /datum/reagents/proc/remove_all_type(reagent_type, amount, strict = FALSE, safety = TRUE) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. if(!isnum(amount)) return TRUE diff --git a/code/modules/research/designs/janitorial_designs.dm b/code/modules/research/designs/janitorial_designs.dm index 4743fb63a17..f744f2d02b3 100644 --- a/code/modules/research/designs/janitorial_designs.dm +++ b/code/modules/research/designs/janitorial_designs.dm @@ -50,3 +50,33 @@ materials = list(MAT_METAL = 1500, MAT_SILVER = 150, MAT_GLASS = 6000, MAT_BLUESPACE = 300) build_path = /obj/item/lightreplacer/bluespace category = list("Janitorial") + +/datum/design/abductor_mop + name = "Alien Mop" + desc = "An advanced mop obtained through Abductor technology." + id = "alien_mop" + req_tech = list("materials" = 5, "engineering" = 5, "abductor" = 3) + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500, MAT_DIAMOND = 1000) + build_path = /obj/item/mop/advanced/abductor + category = list("Janitorial") + +/datum/design/abductor_light_replacer + name = "Alien Light Replacer" + desc = "An advanced light replacer obtained through Abductor technology." + id = "alien_light_replacer" + req_tech = list("bluespace" = 7, "materials" = 5, "engineering" = 5, "abductor" = 3) + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500, MAT_DIAMOND = 1000) + build_path = /obj/item/lightreplacer/bluespace/abductor + category = list("Janitorial") + +/datum/design/abductor_flyswatter + name = "Alien Flyswatter" + desc = "An advanced flyswatter obtained through Abductor technology." + id = "alien_flyswatter" + req_tech = list("combat" = 5, "abductor" = 1) + build_type = PROTOLATHE + materials = list(MAT_METAL = 2000, MAT_SILVER = 1500, MAT_PLASMA = 500, MAT_TITANIUM = 1500, MAT_DIAMOND = 1000) + build_path = /obj/item/melee/flyswatter/abductor + category = list("Janitorial") diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 1de90e4c64d..19fc6461988 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -793,18 +793,18 @@ category = list("Exosuit Equipment") /datum/design/mech_ccw_armor - name = "Exosuit Module (Reactive Armor Booster Module)" + name = "Exosuit Module (Melee Armor Booster Module)" desc = "Exosuit-mounted armor booster." id = "mech_ccw_armor" build_type = MECHFAB - req_tech = list("materials" = 5, "combat" = 4) + req_tech = list("materials" = 5, "combat" = 5, "engineering"=3) build_path = /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster materials = list(MAT_METAL=20000,MAT_SILVER=5000) construction_time = 10 SECONDS category = list("Exosuit Equipment") /datum/design/mech_proj_armor - name = "Exosuit Module (Reflective Armor Booster Module)" + name = "Exosuit Module (Ranged Armor Booster Module)" desc = "Exosuit-mounted armor booster." id = "mech_proj_armor" build_type = MECHFAB @@ -814,6 +814,17 @@ construction_time = 10 SECONDS category = list("Exosuit Equipment") +/datum/design/mech_armor_plate + name = "Exosuit Mining Armor Plate" + desc = "This piece of metal can be attached to the mech itself, enhancing its protective characteristics. Unfortunately, only working class exosuits have notches for such armor." + id = "mech_plate_armor" + build_type = MECHFAB + req_tech = list("materials" = 5, "combat" = 5, "engineering" = 3) + build_path = /obj/item/stack/sheet/animalhide/armor_plate + materials = list(MAT_METAL = 20000, MAT_TITANIUM = 5000) + construction_time = 10 SECONDS + category = list("Exosuit Equipment") + /datum/design/mech_repair_droid name = "Exosuit Module (Repair Droid Module)" desc = "Automated Repair Droid. BEEP BOOP" @@ -1080,6 +1091,16 @@ construction_time = 12 SECONDS category = list("Cyborg Upgrade Modules") +/datum/design/borg_upgrade_abductor_jani + name = "Cyborg Upgrade (Abductor Janitorial Equipment)" + id = "borg_upgade_abductor_jani" + build_type = MECHFAB + build_path = /obj/item/borg/upgrade/abductor_jani + req_tech = list("biotech" = 7, "materials" = 7, "abductor" = 3) + materials = list(MAT_METAL = 10000, MAT_SILVER = 7500, MAT_PLASMA = 2500, MAT_TITANIUM = 7500, MAT_DIAMOND = 5000) //Base abductor jani tools *5 + construction_time = 12 SECONDS + category = list("Cyborg Upgrade Modules") + /datum/design/borg_upgrade_lavaproof name = "Cyborg Upgrade (Lavaproof Chassis)" id = "borg_upgrade_lavaproof" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 476fa574fcf..b929547aa27 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -416,7 +416,7 @@ /datum/design/cyberimp_toolset_abductor name = "Abductor Toolset Implant" - desc = "An alien toolset, designed to be installed on subject's arm." + desc = "An alien toolset, designed to be installed on the subject's arm." id = "ci-hacking" req_tech = list("materials" = 6, "engineering" = 6, "plasmatech" = 6, "abductor" = 4) build_type = PROTOLATHE | MECHFAB @@ -425,6 +425,17 @@ build_path = /obj/item/organ/internal/cyberimp/arm/toolset_abductor category = list("Medical") +/datum/design/cyberimp_janitorial_abductor + name = "Abductor Janitorial Toolset Implant" + desc = "An alien janitorial toolset, designed to be installed on the subject's arm." + id = "ci-jani-abductor" + req_tech = list("materials" = 6, "engineering" = 6, "biotech" = 6, "abductor" = 3) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 20000, MAT_SILVER = 10000, MAT_PLASMA = 9000, MAT_TITANIUM = 8000, MAT_DIAMOND = 8000) + construction_time = 20 SECONDS + build_path = /obj/item/organ/internal/cyberimp/arm/janitorial_abductor + category = list("Medical") + /datum/design/cyberimp_jani_hud name = "Janitor HUD Implant" desc = "These cybernetic eye implants will display a filth HUD over everything you see. Wiggle eyes to control." @@ -502,6 +513,17 @@ build_path = /obj/item/organ/internal/eyes/cybernetic/thermals category = list("Medical") +/datum/design/cyberimp_scope + name = "Kaleido Optics Implant" + desc = "These cybernetic eye implants will let you zoom in on far away objects. Many users find it disorienting, and find it hard to interact with things near them when active." + id = "ci-scope" + req_tech = list("materials" = 6, "programming" = 4, "biotech" = 7, "magnets" = 5,"plasmatech" = 4) + build_type = PROTOLATHE | MECHFAB + construction_time = 60 + materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_DIAMOND = 2000) + build_path = /obj/item/organ/internal/eyes/cybernetic/scope + category = list("Medical") + /datum/design/cyberimp_antidrop name = "Anti-Drop Implant" desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle." diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 45ced9b2403..46189864ab0 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -51,6 +51,16 @@ build_path = /obj/item/disk/tech_disk category = list("Miscellaneous") +/datum/design/training_disk + name = "Training Authentification Disk" + desc = "Replacement authentication disk for the nuclear training bomb." + id = "training_nad" + req_tech = list("programming" = 1) + build_type = PROTOLATHE | AUTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/nuclear/training + category = list("Miscellaneous") + /datum/design/digital_camera name = "Digital Camera" desc = "Produce an enhanced version of the standard issue camera." diff --git a/code/modules/ruins/syndicate_space_base.dm b/code/modules/ruins/syndicate_space_base.dm index 67d9fcc50df..3ec2451c0b6 100644 --- a/code/modules/ruins/syndicate_space_base.dm +++ b/code/modules/ruins/syndicate_space_base.dm @@ -61,6 +61,7 @@ ) /datum/outfit/spacebase_syndicate/post_equip(mob/living/carbon/human/H) + . = ..() H.faction |= "syndicate" var/random_name = random_name(pick(MALE,FEMALE), H.dna.species.name) H.rename_character(H.real_name, random_name) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index cea1e0fae7d..36343d811fa 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -342,12 +342,26 @@ // The emergency shuttle doesn't work like others so this // ripple check is slightly different if(!length(ripples) && (time_left <= SHUTTLE_RIPPLE_TIME) && ((mode == SHUTTLE_CALL) || (mode == SHUTTLE_ESCAPE))) - var/destination + var/obj/docking_port/stationary/destination if(mode == SHUTTLE_CALL) destination = SSshuttle.getDock("emergency_home") else if(mode == SHUTTLE_ESCAPE) destination = SSshuttle.getDock("emergency_away") + if(lance_docking && !destination) + destination = random_docking_go() create_ripples(destination) + if(lance_docking && is_station_level(destination.z)) + var/list/L2 = list() + switch(destination.dir) + if(NORTH) + L2 = block(locate(destination.x-9, destination.y+36, destination.z), locate(destination.x+9, 255, destination.z)) + if(SOUTH) + L2 = block(locate(destination.x-9, 1, destination.z), locate(destination.x+9, destination.y-36, destination.z)) + if(EAST) + L2 = block(locate(destination.x+36, destination.y-9, destination.z), locate(255, destination.y+9, destination.z)) + if(WEST) + L2 = block(locate(1, destination.y-9, destination.z), locate(destination.x-36, destination.y+9, destination.z)) + create_lance_ripples(L2, destination) switch(mode) if(SHUTTLE_RECALL) @@ -443,6 +457,55 @@ D.open() */ //Leaving this here incase someone decides to port -tg-'s escape shuttle stuff: +/obj/docking_port/mobile/emergency/proc/random_docking_go() + var/cycles = 1000 + var/stop = FALSE + for(var/cycle in 1 to cycles) + // DRUNK DIALLING WOOOOOOOOO + var/x = rand(1, world.maxx) + var/y = rand(1, world.maxy) + var/z = 2 + var/random_dir = pick(NORTH, SOUTH, EAST, WEST) + var/obj/docking_port/stationary/lance/port = new(locate(x, y, z)) + port.dir = random_dir + if(isspaceturf(get_turf(port))) + qdel(port, force = TRUE) + continue + + var/min_x = -1 + var/min_y = -1 + var/max_x = -1 + var/max_y = -1 + + var/list/ordered_turfs = port.return_ordered_turfs() + for(var/turf/T in ordered_turfs) + if(stop) + break + min_x = min_x < 0 ? T.x : min(min_x, T.x) + min_y = min_y < 0 ? T.y : min(min_y, T.y) + max_x = max_x < 0 ? T.x : max(max_x, T.x) + max_y = max_y < 0 ? T.y : max(max_y, T.y) + for(var/obj/O in T.contents) + if(istype(O, /obj/machinery/atmospherics/supermatter_crystal) || istype(O, /obj/singularity)) + qdel(port, force = TRUE) + stop = TRUE + break + if(stop) + stop = FALSE + continue + if(min_x <= TRANSITION_BORDER_WEST + 1 || max_x >= TRANSITION_BORDER_EAST - 1) + qdel(port, force = TRUE) + continue + if(min_y <= TRANSITION_BORDER_SOUTH + 1 || max_y >= TRANSITION_BORDER_NORTH - 1) + qdel(port, force = TRUE) + continue + port.register() + return port + +/obj/docking_port/mobile/emergency/proc/create_lance_ripples(list/L2, obj/docking_port/stationary/S1) + for(var/turf/T in L2) + ripples += new /obj/effect/temp_visual/ripple/lance_crush(T) + // This basically opens a big-ass row of blast doors when the shuttle arrives at centcom /obj/docking_port/mobile/pod name = "escape pod" diff --git a/code/modules/shuttle/lance_docking_targeter.dm b/code/modules/shuttle/lance_docking_targeter.dm new file mode 100644 index 00000000000..f758267d20b --- /dev/null +++ b/code/modules/shuttle/lance_docking_targeter.dm @@ -0,0 +1,118 @@ +/obj/item/lance_docking_generator + name = "lance docking beacon" + desc = "A signaling device used to place a beacon, to allow the lance to precicely dock." + icon = 'icons/obj/device.dmi' + icon_state = "gangtool-red" + var/gps + +/obj/item/lance_docking_generator/Initialize(mapload) + . = ..() + gps = new /obj/item/gps/internal/lance_beacon(src) + +/obj/item/lance_docking_generator/Destroy() + qdel(gps) + return ..() + +/obj/item/lance_docking_generator/emag_act(mob/user) + if(!emagged) + emagged = TRUE + to_chat(user, "You emag [src], removing its docking safeties.") + var/turf/T = get_turf(src) + do_sparks(5, FALSE, T) + playsound(T, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return TRUE + +/obj/item/lance_docking_generator/attack_self(mob/living/user) + if(!is_station_level(user.z)) + to_chat(user, "You'll want this to dock on the station.") + return + var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST) + var/dir_choice = tgui_input_list(user, "Select the new docking area orientation.", "Dock Orientation", dir_choices) + if(!dir_choice) + return + + var/dest_dir = dir_choices[dir_choice] + var/turf/destination = get_step(user.loc, dest_dir) + var/obj/docking_port/stationary/lance/port = new(destination) + port.dir = dest_dir + + var/min_x = -1 + var/min_y = -1 + var/max_x = -1 + var/max_y = -1 + + var/list/ordered_turfs = port.return_ordered_turfs() + for(var/turf/T in ordered_turfs) + min_x = min_x < 0 ? T.x : min(min_x, T.x) + min_y = min_y < 0 ? T.y : min(min_y, T.y) + max_x = max_x < 0 ? T.x : max(max_x, T.x) + max_y = max_y < 0 ? T.y : max(max_y, T.y) + for(var/obj/O in T.contents) + if((istype(O, /obj/machinery/atmospherics/supermatter_crystal) || istype(O, /obj/singularity)) && !emagged) + to_chat(user, "Dangerous landing conditions, aborting!") + qdel(port, force = TRUE) + return + + if(min_x <= TRANSITION_BORDER_WEST + 1 || max_x >= TRANSITION_BORDER_EAST - 1) + to_chat(user, "Docking space area too close to edge of sector, aborting!") + qdel(port, force = TRUE) + return + if(min_y <= TRANSITION_BORDER_SOUTH + 1 || max_y >= TRANSITION_BORDER_NORTH - 1) + to_chat(user, "Docking space area too close to edge of sector, aborting!") + qdel(port, force = TRUE) + return + var/list/L2 = list() + switch(dest_dir) + if(NORTH) + L2 = block(locate(port.x - 9, port.y + 36, port.z), locate(port.x + 9, 255, port.z)) + if(SOUTH) + L2 = block(locate(port.x - 9, 1, port.z), locate(port.x + 9, port.y - 36, port.z)) + if(EAST) + L2 = block(locate(port.x + 36, port.y - 9, port.z), locate(255, port.y + 9, port.z)) + if(WEST) + L2 = block(locate(1, port.y - 9, port.z), locate(port.x - 36, port.y + 9, port.z)) + for(var/turf/BT in L2) + for(var/obj/Ohno in BT.contents) + if((istype(Ohno, /obj/machinery/atmospherics/supermatter_crystal) || istype(Ohno, /obj/singularity)) && !emagged) + to_chat(user, "Dangerous landing conditions, aborting!") + qdel(port, force = TRUE) + return + port.register() + + log_admin("[key_name(user)] created the lance docking location at [COORD(port)].") + to_chat(user, "Landing zone set. The signaller vanishes!") + new /obj/structure/lance_beacon(get_turf(src)) + qdel(src) + +/obj/structure/lance_beacon + name = "lance docking beacon" + desc = "A beacon that allows the Lance to carefully slam into the station at plasteel destroying speeds." + icon = 'icons/obj/singularity.dmi' + icon_state = "beacon1" + layer = MOB_LAYER - 0.2 //so people can't hide it and it's REALLY OBVIOUS + anchored = TRUE + resistance_flags = INDESTRUCTIBLE + var/gps + +/obj/structure/lance_beacon/Initialize(mapload) + . = ..() + gps = new /obj/item/gps/internal/lance_beacon(src) + set_light(5, 3, COLOR_WARM_YELLOW) + +/obj/structure/lance_beacon/Destroy() + qdel(gps) + return ..() + +/obj/docking_port/stationary/lance + name = "lance docking port" + id = "emergency_home" + height = 50 + dheight = 0 + width = 19 + dwidth = 9 + +/obj/item/gps/internal/lance_beacon + icon_state = null + gpstag = "Lance Docking Beacon" + desc = "It is not reccomended to stand here." + invisibility = 100 diff --git a/code/modules/shuttle/ripple.dm b/code/modules/shuttle/ripple.dm index 078cc9aa9fa..bc7ba0e05ed 100644 --- a/code/modules/shuttle/ripple.dm +++ b/code/modules/shuttle/ripple.dm @@ -20,3 +20,19 @@ . = ..() QUEUE_SMOOTH(src) animate(src, alpha=255, time=SHUTTLE_RIPPLE_TIME) + + +/obj/effect/temp_visual/ripple/lance_crush + name = "collision lights" + desc = "Something is coming through hyperspace in a very unsafe way. You *really* do not want to be standing here." + icon = 'icons/turf/walls/hierophant_wall_temp.dmi' + icon_state = "hierophant_wall_temp-0" + base_icon_state = "hierophant_wall_temp" + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = list(SMOOTH_GROUP_HIERO_WALL) + canSmoothWith = list(SMOOTH_GROUP_HIERO_WALL) + color = rgb(255, 0, 0) + light_range = MINIMUM_USEFUL_LIGHT_RANGE + light_color = LIGHT_COLOR_PURE_RED + alpha = 128 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 70c8c5e4646..12776a8ccea 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -228,6 +228,8 @@ var/uses_lockdown = FALSE /// If this variable is true, shuttle is on lockdown, and other requests can not be processed var/lockeddown = FALSE + /// Is this a shuttle that completely destroys whatever dares to get in it's way? + var/lance_docking = FALSE /obj/docking_port/mobile/Initialize(mapload) . = ..() @@ -479,6 +481,18 @@ remove_ripples() //move or squish anything in the way ship at destination + if(lance_docking && is_station_level(S1.z)) + var/list/L2 = list() + switch(S1.dir) + if(NORTH) + L2 = block(locate(S1.x-9, S1.y+36, S1.z), locate(S1.x+9, 255, S1.z)) + if(SOUTH) + L2 = block(locate(S1.x-9, 1, S1.z), locate(S1.x+9, S1.y-36, S1.z)) + if(EAST) + L2 = block(locate(S1.x+36, S1.y-9, S1.z), locate(255, S1.y+9, S1.z)) + if(WEST) + L2 = block(locate(1, S1.y-9, S1.z), locate(S1.x-36, S1.y+9, S1.z)) + shuttle_smash(L2, S1) roadkill(L0, L1, S1.dir) for(var/i in 1 to length(L0)) @@ -614,6 +628,9 @@ if(AM.pulledby) AM.pulledby.stop_pulling() if(AM.flags_2 & IMMUNE_TO_SHUTTLECRUSH_2) + if(istype(AM, /obj/machinery/atmospherics/supermatter_crystal)) + var/obj/machinery/atmospherics/supermatter_crystal/bakoom = AM + addtimer(CALLBACK(bakoom, TYPE_PROC_REF(/obj/machinery/atmospherics/supermatter_crystal, explode), bakoom.combined_gas, bakoom.power, bakoom.gasmix_power_ratio), 1 SECONDS) continue if(ismob(AM)) var/mob/M = AM @@ -627,6 +644,18 @@ "You feel an immense \ crushing pressure as the space around you ripples.") L.gib() + else if(lance_docking) //corrupt the child, destroy them all + if(!AM.simulated) + continue + if(istype(AM, /mob/dead)) + continue + if(istype(AM, /obj/item/organ)) + continue + if(istype(AM, /obj/effect/landmark)) + continue + if(istype(AM, /obj/docking_port)) + continue + qdel(AM, force = TRUE) // Move unanchored atoms if(!AM.anchored && !ismob(AM)) @@ -635,6 +664,21 @@ if(AM.simulated) // Don't qdel lighting overlays, they are static qdel(AM) +/obj/docking_port/mobile/proc/shuttle_smash(list/L2, obj/docking_port/stationary/S1) + var/loud_crash_sound = sound('sound/effects/explosioncreak1.ogg') + for(var/player in GLOB.player_list) + var/mob/M = player + var/turf/mob_turf = get_turf(M) + if(atoms_share_level(S1, mob_turf)) + SEND_SOUND(M, loud_crash_sound) + for(var/turf/T in L2) + for(var/atom/movable/A in T.contents) + A.ex_act(1) + if(istype(A, /obj/machinery/atmospherics/supermatter_crystal)) + var/obj/machinery/atmospherics/supermatter_crystal/bakoom = A + addtimer(CALLBACK(bakoom, TYPE_PROC_REF(/obj/machinery/atmospherics/supermatter_crystal, explode), bakoom.combined_gas, bakoom.power, bakoom.gasmix_power_ratio), 1 SECONDS) + T.ChangeTurf(T.baseturf) //I don't want to deal with turf decals + //used by shuttle subsystem to check timers /obj/docking_port/mobile/proc/check() check_effects() diff --git a/code/modules/shuttle/shuttle_manipulator.dm b/code/modules/shuttle/shuttle_manipulator.dm index c8417758b61..36d822cbdf4 100644 --- a/code/modules/shuttle/shuttle_manipulator.dm +++ b/code/modules/shuttle/shuttle_manipulator.dm @@ -203,6 +203,9 @@ /obj/machinery/shuttle_manipulator/proc/action_load(datum/map_template/shuttle/loading_template) if(isnull(loading_template)) CRASH("No template passed.") + if(istype(loading_template, /datum/map_template/shuttle/emergency) && SSshuttle.emergency_locked_in) + message_admins("The emergency shuttle has been locked in. You can not load another shuttle.") + return if(preview_shuttle && (loading_template != preview_template)) preview_shuttle.jumpToNullSpace() @@ -221,6 +224,10 @@ selected = null /obj/machinery/shuttle_manipulator/proc/action_load_old(datum/map_template/shuttle/loading_template) + if(istype(loading_template, /datum/map_template/shuttle/emergency) && SSshuttle.emergency_locked_in) + message_admins("The emergency shuttle has been locked in. You can not load another shuttle.") + return + // Check for an existing preview if(preview_shuttle && (loading_template != preview_template)) preview_shuttle.jumpToNullSpace() @@ -240,6 +247,8 @@ timer = existing_shuttle.timer mode = existing_shuttle.mode D = existing_shuttle.get_docked() + if(!D) //lance moment + D = SSshuttle.getDock("emergency_away") else D = preview_shuttle.findRoundstartDock() diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 6fdcf267a14..9853fc4e78b 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -294,6 +294,7 @@ var/msg = "
---[station_time_timestamp()]---

" var/list/credit_changes = list() + var/list/department_messages = list() for(var/datum/economy/line_item/item in manifest.line_items) if(!credit_changes[item.account]) credit_changes[item.account] = 0 @@ -306,6 +307,13 @@ else msg += "[item.account.account_name] [item.credits]: [item.reason]
" + if(item.requests_console_department) + if(!department_messages[item.requests_console_department]) + department_messages[item.requests_console_department] = list() + if(!department_messages[item.requests_console_department][item.reason]) + department_messages[item.requests_console_department][item.reason] = 0 + department_messages[item.requests_console_department][item.reason]++ + for(var/datum/money_account/account in credit_changes) if(account.account_type == ACCOUNT_TYPE_DEPARTMENT) SSblackbox.record_feedback("tally", "cargo profits", credit_changes[account], "[account.account_name]") @@ -317,6 +325,15 @@ else GLOB.station_money_database.charge_account(account, -credit_changes[account], "Supply Shuttle Fine", "Central Command Supply Master", allow_overdraft = TRUE, supress_log = FALSE) + for(var/department in department_messages) + var/list/rc_message = list() + for(var/message_piece in department_messages[department]) + var/count = "" + if(department_messages[department][message_piece] > 1) + count = " (x[department_messages[department][message_piece]])" + rc_message += "[message_piece][count]" + send_requests_console_message(rc_message, "Central Command", department, "Stamped with the Central Command rubber stamp.", "Verified by the Central Command receiving department.", RQ_NORMALPRIORITY) + SSeconomy.centcom_message += "[msg]
" manifest = new @@ -802,6 +819,7 @@ /datum/economy/line_item var/datum/money_account/account + var/requests_console_department var/credits var/reason var/zero_is_good = FALSE diff --git a/code/modules/station_goals/secondary/botany/kudzu_goal.dm b/code/modules/station_goals/secondary/botany/kudzu_goal.dm index 68387c00754..d77445775a1 100644 --- a/code/modules/station_goals/secondary/botany/kudzu_goal.dm +++ b/code/modules/station_goals/secondary/botany/kudzu_goal.dm @@ -65,6 +65,7 @@ item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE) item.credits = 0 item.reason = "[AM] does not have the right traits." + item.requests_console_department = "Hydroponics" manifest.line_items += item return COMSIG_CARGO_SELL_WRONG @@ -79,27 +80,12 @@ update_item.credits = 0 update_item.zero_is_good = TRUE update_item.reason = "Received [sent_this_shipment] useful samples of kudzu seeds." + update_item.requests_console_department = "Hydroponics" manifest.line_items += update_item if(sent < needed) return - var/datum/economy/line_item/supply_item = new - supply_item.account = SSeconomy.cargo_account - supply_item.credits = SSeconomy.credits_per_kudzu_goal / 3 - supply_item.reason = "Secondary goal complete: [needed] samples of kudzu seeds." - manifest.line_items += supply_item - - var/datum/economy/line_item/department_item = new - department_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE) - department_item.credits = SSeconomy.credits_per_kudzu_goal / 3 - department_item.reason = "Secondary goal complete: [needed] samples of kudzu seeds." - manifest.line_items += department_item - - var/datum/economy/line_item/personal_item = new - personal_item.account = personal_account || department_item.account - personal_item.credits = SSeconomy.credits_per_kudzu_goal / 3 - personal_item.reason = "Secondary goal complete: [needed] samples of kudzu seeds." - manifest.line_items += personal_item + three_way_reward(manifest, "Hydroponics", GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE), SSeconomy.credits_per_kudzu_goal, "Secondary goal complete: [needed] samples of kudzu seeds.") return TRUE diff --git a/code/modules/station_goals/secondary/kitchen/random_bulk_food.dm b/code/modules/station_goals/secondary/kitchen/random_bulk_food.dm index 7580945d711..cc3296af2f1 100644 --- a/code/modules/station_goals/secondary/kitchen/random_bulk_food.dm +++ b/code/modules/station_goals/secondary/kitchen/random_bulk_food.dm @@ -13,6 +13,8 @@ var/obj/item/food/snacks/candidate = S if(initial(candidate.goal_difficulty) == FOOD_GOAL_SKIP) continue + if(initial(candidate.goal_difficulty) == FOOD_GOAL_EXCESSIVE) + continue valid_food += candidate if(!valid_food) @@ -83,6 +85,7 @@ update_item.credits = 0 update_item.zero_is_good = TRUE update_item.reason = "Received [sent_this_shipment] servings of [initial(food_type.name)]." + update_item.requests_console_department = "Kitchen" manifest.line_items += update_item if(sent < needed) diff --git a/code/modules/station_goals/secondary/kitchen/variety_food.dm b/code/modules/station_goals/secondary/kitchen/variety_food.dm new file mode 100644 index 00000000000..66144ba2477 --- /dev/null +++ b/code/modules/station_goals/secondary/kitchen/variety_food.dm @@ -0,0 +1,117 @@ +/datum/station_goal/secondary/variety_food + name = "Variety of Food" + progress_type = /datum/secondary_goal_progress/variety_food + department = "Kitchen" + abstract = FALSE + /// How many different types of food are needed. + var/different_types = 10 + /// How many of each food type are needed. + var/amount_per = 3 + var/department_account + var/generic_name_plural = "dishes" + var/reward + +/datum/station_goal/secondary/variety_food/randomize_params() + ..() + department_account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE) + report_message = "We're holding a fundraising banquet, and we need a suitable spread of food for it. Send us at least [amount_per] servings of [different_types] different dishes." + +/datum/station_goal/secondary/variety_food/Initialize(requester_account) + reward = SSeconomy.credits_per_variety_food_goal + ..() + admin_desc = "[amount_per] units of [different_types] [generic_name_plural]" + +/datum/secondary_goal_progress/variety_food + var/list/foods_sent = list() + var/department + var/needed + var/amount_per + var/department_account + var/reward + var/generic_name_plural + +/datum/secondary_goal_progress/variety_food/configure(datum/station_goal/secondary/variety_food/goal) + ..() + department = goal.department + needed = goal.different_types + amount_per = goal.amount_per + department_account = goal.department_account + reward = goal.reward + generic_name_plural = goal.generic_name_plural + +/datum/secondary_goal_progress/variety_food/Copy() + var/datum/secondary_goal_progress/variety_food/copy = ..() + copy.foods_sent = foods_sent.Copy() + copy.department = department + copy.needed = needed + copy.amount_per = amount_per + // These ones aren't really needed in the intended use case, they're + // just here in case someone uses this method somewhere else. + copy.department_account = department_account + copy.reward = reward + copy.generic_name_plural = generic_name_plural + return copy + +/datum/secondary_goal_progress/variety_food/update(obj/item/food/food, datum/economy/cargo_shuttle_manifest/manifest = null) + // Not in a matching personal crate? Ignore. + if(!check_personal_crate(food)) + return + + // Not food? Ignore. + if(!istype(food)) + return + + // No easy foods allowed. + if(food.goal_difficulty == FOOD_GOAL_SKIP) + if(!manifest) + return COMSIG_CARGO_SELL_WRONG + SSblackbox.record_feedback("nested tally", "secondary goals", 1, list(goal_name, "boring foods")) + var/datum/economy/line_item/item = new + item.account = department_account + item.credits = 0 + item.reason = "We don't need [food.name]. Send something better." + item.requests_console_department = "Kitchen" + manifest.line_items += item + return COMSIG_CARGO_SELL_WRONG + + if(foods_sent[food.type] >= amount_per) + if(!manifest) + return COMSIG_CARGO_SELL_WRONG + SSblackbox.record_feedback("nested tally", "secondary goals", 1, list(goal_name, "repeat foods")) + var/datum/economy/line_item/item = new + item.account = department_account + item.credits = 0 + item.reason = "You already sent us enough [food.name]." + item.requests_console_department = "Kitchen" + manifest.line_items += item + return COMSIG_CARGO_SELL_WRONG + + if(!foods_sent[food.type]) + foods_sent[food.type] = 0 + foods_sent[food.type]++ + + if(!manifest) + return COMSIG_CARGO_SELL_PRIORITY + SSblackbox.record_feedback("nested tally", "secondary goals", 1, list(goal_name, "valid foods")) + SSblackbox.record_feedback("nested tally", "secondary goals", 1, list(goal_name, "foods", initial(food.name))) + var/datum/economy/line_item/item = new() + item.account = department_account + item.credits = 0 + item.reason = "Received [initial(food.name)]." + item.zero_is_good = TRUE + item.requests_console_department = "Kitchen" + manifest.line_items += item + return COMSIG_CARGO_SELL_PRIORITY + +/datum/secondary_goal_progress/variety_food/check_complete(datum/economy/cargo_shuttle_manifest/manifest) + var/complete_foods = 0 + for(var/food_type in foods_sent) + if(foods_sent[food_type] >= amount_per) + complete_foods++ + SSblackbox.record_feedback("nested tally", "secondary goals", 1, list(goal_name, "complete foods")) + + if(complete_foods < needed) + return FALSE + + three_way_reward(manifest, department, department_account, reward, "Secondary goal complete: [needed] different [generic_name_plural].") + return TRUE diff --git a/code/modules/station_goals/secondary/random_bulk_reagent.dm b/code/modules/station_goals/secondary/random_bulk_reagent.dm index 8dc35f4fd58..f1b6e9fc17a 100644 --- a/code/modules/station_goals/secondary/random_bulk_reagent.dm +++ b/code/modules/station_goals/secondary/random_bulk_reagent.dm @@ -17,6 +17,10 @@ if(initial(candidate.goal_department) != department) continue if(initial(candidate.goal_difficulty) == REAGENT_GOAL_SKIP) + // Too easy, don't want. + continue + if(initial(candidate.goal_difficulty) == REAGENT_GOAL_EXCESSIVE) + // Too hard, don't ask for. continue valid_reagents += candidate @@ -84,6 +88,7 @@ item.account = department_account item.credits = 0 item.reason = "Received [amount] units of [initial(reagent_type.name)]." + item.requests_console_department = department item.zero_is_good = TRUE manifest.line_items += item diff --git a/code/modules/station_goals/secondary/science/random_ripley.dm b/code/modules/station_goals/secondary/science/random_ripley.dm index 113b5c4601b..33d63b6cf32 100644 --- a/code/modules/station_goals/secondary/science/random_ripley.dm +++ b/code/modules/station_goals/secondary/science/random_ripley.dm @@ -70,8 +70,8 @@ extra_item.account = SSeconomy.cargo_account extra_item.credits = SSeconomy.credits_per_mech extra_item.reason = "We already got the mech we needed, but we'll take this one at the usual price." + extra_item.requests_console_department = "Robotics" manifest.line_items += extra_item - send_requests_console_message(extra_item.reason, "Central Command", "Robotics", "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_PRIORITY | COMSIG_CARGO_IS_SECURED var/remaining_needs = modules.Copy() @@ -89,9 +89,9 @@ var/datum/economy/line_item/wrong_item = new wrong_item.account = SSeconomy.cargo_account wrong_item.credits = SSeconomy.credits_per_mech - wrong_item.reason = "That's not the equipment we needed, but it's still a mech" + wrong_item.reason = "That's not the equipment we needed, but it's still a mech, so we'll take it at the usual price." + wrong_item.requests_console_department = "Robotics" manifest.line_items += wrong_item - send_requests_console_message(wrong_item.reason + ", so we sent the usual amount to your supply account.", "Central Command", "Robotics", "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_PRIORITY | COMSIG_CARGO_IS_SECURED sent = TRUE diff --git a/code/modules/station_goals/secondary/secondary_goal_tracker.dm b/code/modules/station_goals/secondary/secondary_goal_tracker.dm index 498c4215920..edee8140029 100644 --- a/code/modules/station_goals/secondary/secondary_goal_tracker.dm +++ b/code/modules/station_goals/secondary/secondary_goal_tracker.dm @@ -129,6 +129,6 @@ personal_item.account = personal_account || department_account personal_item.credits = reward / 3 personal_item.reason = message + personal_item.requests_console_department = department manifest.line_items += personal_item - send_requests_console_message(message, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) diff --git a/code/modules/station_goals/secondary/variety_reagent.dm b/code/modules/station_goals/secondary/variety_reagent.dm index 19cff7feb5b..14665b20a8c 100644 --- a/code/modules/station_goals/secondary/variety_reagent.dm +++ b/code/modules/station_goals/secondary/variety_reagent.dm @@ -68,8 +68,8 @@ item.account = department_account item.credits = 0 item.reason = "That [reagent.name] seems to be mixed with something else. Send it by itself, please." + item.requests_console_department = department manifest.line_items += item - send_requests_console_message(item.reason, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_WRONG // No easy reagents allowed. @@ -81,8 +81,8 @@ item.account = department_account item.credits = 0 item.reason = "We don't need [reagent.name]. Send something better." + item.requests_console_department = department manifest.line_items += item - send_requests_console_message(item.reason, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_WRONG // Make sure there's enough. @@ -94,8 +94,8 @@ item.account = department_account item.credits = 0 item.reason = "That batch of [reagent.name] was too small; send at least [amount_per] units." + item.requests_console_department = department manifest.line_items += item - send_requests_console_message(item.reason, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_WRONG if(reagents_sent[reagent.id]) @@ -106,8 +106,8 @@ item.account = department_account item.credits = 0 item.reason = "You already sent us [reagent.name]." + item.requests_console_department = department manifest.line_items += item - send_requests_console_message(item.reason, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_WRONG reagents_sent[reagent.id] = TRUE @@ -120,9 +120,9 @@ item.account = department_account item.credits = 0 item.reason = "Received [initial(reagent.name)]." + item.requests_console_department = department item.zero_is_good = TRUE manifest.line_items += item - send_requests_console_message(item.reason, "Central Command", department, "Stamped with the Central Command rubber stamp.", null, RQ_NORMALPRIORITY) return COMSIG_CARGO_SELL_PRIORITY /datum/secondary_goal_progress/variety_reagent/check_complete(datum/economy/cargo_shuttle_manifest/manifest) diff --git a/code/modules/supply/supply_packs/pack_shuttle.dm b/code/modules/supply/supply_packs/pack_shuttle.dm index 4a5ba2d7703..2425a61026b 100644 --- a/code/modules/supply/supply_packs/pack_shuttle.dm +++ b/code/modules/supply/supply_packs/pack_shuttle.dm @@ -40,6 +40,8 @@ . = ..() if(SSshuttle.custom_shuttle_ordered) return + if(SSshuttle.emergency_locked_in) + return if(isnull(template)) CRASH("Shuttle pack [src] has no map template to load!") GLOB.major_announcement.Announce("[order.orderedby] has purchased [name] for [cost] credit\s as the emergency shuttle for the shift.", "Shuttle Purchase Receipt") @@ -54,6 +56,8 @@ var/obj/docking_port/mobile/shuttle = SSshuttle.load_template(template) shuttle.shuttle_speed_factor = speed_factor SSshuttle.replace_shuttle(shuttle) + SSshuttle.emergency_locked_in = TRUE + return TRUE /// Simple supply pack for easy admin modification /datum/supply_packs/abstract/admin_notify/donations @@ -98,6 +102,35 @@ template = /datum/map_template/shuttle/emergency/shadow speed_factor = 2 //Fast enough that it probably won't burn down entirely after the crew looses the plasma +/datum/supply_packs/abstract/shuttle/lance + cost = 5000 //please don't order this for funny please sir + template = /datum/map_template/shuttle/emergency/lance + speed_factor = 1.5 //Don't need to slow down before docking + +/datum/supply_packs/abstract/shuttle/lance/on_order_confirm(datum/supply_order/order) + . = ..() + if(!.) + return + if(order.orderedby) + for(var/mob/living/carbon/human/H in GLOB.human_list) + if(H.name == order.orderedby) + new /obj/item/lance_docking_generator(get_turf(H)) + GLOB.major_announcement.Announce("[order.orderedby] has had a beacon placer teleported to them!", "Shuttle Purchase Receipt") + return TRUE + GLOB.major_announcement.Announce("We were unable to find an orderer. We have sent the beacon placer to the Cargo Office.", "Shuttle Purchase Receipt") + var/list/L = list() + for(var/turf/T in get_area_turfs(/area/station/supply/office)) + if(is_blocked_turf(T)) + continue + L.Add(T) + + if(!length(L)) + GLOB.major_announcement.Announce("We... couldn't find cargo? Well. We'll crash somewhere into your station.", "WELP") + return TRUE + + new /obj/item/lance_docking_generator(pick(L)) + return TRUE + // these, otoh, have some pretty silly features, and are hidden behind emag /datum/supply_packs/abstract/shuttle/clown diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 2c7806b9dce..f28c4636559 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -250,6 +250,17 @@ /obj/item/organ/internal/cyberimp/arm/toolset_abductor/l parent_organ = "l_arm" +/obj/item/organ/internal/cyberimp/arm/janitorial_abductor + name = "alien janitorial toolset implant" + desc = "A set of alien janitorial tools, designed to be installed on subject's arm." + origin_tech = "materials=5;engineering=5;biotech=5;powerstorage=4;abductor=3" + contents = newlist(/obj/item/mop/advanced/abductor, /obj/item/soap/syndie/abductor, /obj/item/lightreplacer/bluespace/abductor, /obj/item/holosign_creator/janitor, /obj/item/melee/flyswatter/abductor, /obj/item/reagent_containers/spray/cleaner/safety/abductor) + action_icon = list(/datum/action/item_action/organ_action/toggle = 'icons/obj/abductor.dmi') + action_icon_state = list(/datum/action/item_action/organ_action/toggle = "janibelt_abductor") + +/obj/item/organ/internal/cyberimp/arm/janitorial_abductor/l + parent_organ = "l_arm" + /obj/item/organ/internal/cyberimp/arm/esword name = "arm-mounted energy blade" desc = "An illegal, and highly dangerous cybernetic implant that can project a deadly blade of concentrated enregy." diff --git a/code/modules/surgery/organs/autosurgeon.dm b/code/modules/surgery/organs/autosurgeon.dm index 69678826def..427b07d51f3 100644 --- a/code/modules/surgery/organs/autosurgeon.dm +++ b/code/modules/surgery/organs/autosurgeon.dm @@ -141,6 +141,9 @@ /obj/item/autosurgeon/organ/syndicate/xray_eyes starting_organ = /obj/item/organ/internal/eyes/cybernetic/xray/hardened +/obj/item/autosurgeon/organ/syndicate/scope_eyes + starting_organ = /obj/item/organ/internal/eyes/cybernetic/scope/hardened + /obj/item/autosurgeon/organ/syndicate/anti_stam starting_organ = /obj/item/organ/internal/cyberimp/brain/anti_stam/hardened diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 373303286c6..a7b13fe9aff 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -167,6 +167,38 @@ emp_proof = TRUE origin_tech = "materials=6;programming=5;biotech=6;magnets=6;syndicate=3" +/obj/item/organ/internal/eyes/cybernetic/scope + name = "\improper Kaleido Optics eyes" + desc = "These cybernetic eye implants will let you zoom in on far away objects. Many users find it disorienting, and find it hard to interact with things near them when active." + eye_color = "#6f00ff" + flash_protect = FLASH_PROTECTION_EXTRA_SENSITIVE + origin_tech = "materials=5;programming=4;biotech=4;magnets=4" + var/scope_range = 0.8 //Only used in initialize. Greatly nerfed zoom range, since you are not taking the time zoom delay the lwap has. + var/active = FALSE + +/obj/item/organ/internal/eyes/cybernetic/scope/Initialize(mapload) + . = ..() + AddComponent(/datum/component/scope, range_modifier = scope_range, item_action_type = /datum/action/item_action/organ_action/toggle, allow_middle_click = TRUE) + +/obj/item/organ/internal/eyes/cybernetic/scope/insert(mob/living/carbon/human/M, special) + . = ..() + flash_protect = FLASH_PROTECTION_NONE //Resets it to none, so we can just flip to inital each time it is used. + +/obj/item/organ/internal/eyes/cybernetic/scope/ui_action_click(mob/user, actiontype) + active = !active + if(active) + flash_protect = initial(flash_protect) + else + flash_protect = FLASH_PROTECTION_NONE + +/obj/item/organ/internal/eyes/cybernetic/scope/hardened + name = "\improper Hardened Kaleido Optics eyes" + desc = "These cybernetic eye implants will let you zoom in on far away objects. Many users find it disorienting, and find it hard to interact with things near them when active. This pair has been hardened for special operations personnel, and has enhanced zoom functionality." + flash_protect = FLASH_PROTECTION_SENSITIVE + origin_tech = "materials=6;programming=5;biotech=6;magnets=6;syndicate=3" + scope_range = 1.25 + emp_proof = TRUE + /obj/item/organ/internal/eyes/cybernetic/flashlight name = "flashlight eyes" desc = "It's two flashlights rigged together with some wire. Why would you put these in someone's head?" diff --git a/code/modules/surgery/organs/organ_extractor.dm b/code/modules/surgery/organs/organ_extractor.dm index 02f54d36d63..efa581b8bc3 100644 --- a/code/modules/surgery/organs/organ_extractor.dm +++ b/code/modules/surgery/organs/organ_extractor.dm @@ -140,6 +140,9 @@ if(replaced) //Lets not destroy someones brain fully by putting someone elses brain in that slot. replaced.remove(C) replaced.forceMove(get_turf(src)) + if(istype(storedorgan, /obj/item/organ/internal/heart) && ((/obj/item/organ/internal/cyberimp/brain/sensory_enhancer in C.internal_organs) || C.reagents.addiction_threshold_accumulated[/datum/reagent/mephedrone])) + storedorgan.damage = 40 // Damage the heart so you can't endlessly OD for cheap easily. + to_chat(user, "CAUTION: Crystalized mephedrone has bounced off the drill into [storedorgan], causing internal damage!") storedorgan.insert(C) playsound(get_turf(C), 'sound/weapons/circsawhit.ogg', 50, TRUE) storedorgan = null diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index fbc2ef27130..6f22fb03501 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -216,7 +216,7 @@ if(accept_hand) if(!tool) success = TRUE - if(isrobot(user) && istype(tool, /obj/item/gripper_medical)) + if(isrobot(user) && istype(tool, /obj/item/gripper/medical)) success = TRUE if(accept_any_item) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 6009508a7fc..e711b0cf231 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -1,6 +1,6 @@ /obj/item/retractor name = "retractor" - desc = "Retracts stuff." + desc = "A sterilized tissue retractor used for holding open incisions." icon = 'icons/obj/surgery.dmi' icon_state = "retractor" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -22,7 +22,7 @@ /obj/item/hemostat name = "hemostat" - desc = "You think you have seen this before." + desc = "A sterilized steel surgical clamp for sealing exposed blood vessels during surgery." icon = 'icons/obj/surgery.dmi' icon_state = "hemostat" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -44,7 +44,7 @@ /obj/item/cautery name = "cautery" - desc = "This stops bleeding." + desc = "A unipolar electrocauter used to sear surgical incisions shut." icon = 'icons/obj/surgery.dmi' icon_state = "cautery" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -66,7 +66,7 @@ /obj/item/surgicaldrill name = "surgical drill" - desc = "You can drill using this item. You dig?" + desc = "A sterilized drill used to create holes in bone and teeth." icon = 'icons/obj/surgery.dmi' icon_state = "drill" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -99,7 +99,7 @@ /obj/item/scalpel name = "scalpel" - desc = "Cut, cut, and once more cut." + desc = "A sterilized stainless steel cutting implement for making precise surgical incisions." icon = 'icons/obj/surgery.dmi' icon_state = "scalpel" item_state = "scalpel" @@ -141,7 +141,7 @@ /// parent type /obj/item/scalpel/laser name = "laser scalpel" - desc = "A scalpel augmented with a directed laser." + desc = "A low-power laser emitter for creating and cauterizing precise surgical incisions." icon_state = "scalpel_laser1_on" damtype = "fire" hitsound = 'sound/weapons/sear.ogg' @@ -149,19 +149,19 @@ /// lasers also count as catuarys /obj/item/scalpel/laser/laser1 name = "laser scalpel" - desc = "A scalpel augmented with a directed laser. This one looks basic and could be improved." + desc = "A basic low-power laser emitter for creating and cauterizing precise surgical incisions." icon_state = "scalpel_laser1_on" toolspeed = 0.8 /obj/item/scalpel/laser/laser2 name = "laser scalpel" - desc = "A scalpel augmented with a directed laser. This one looks somewhat advanced." + desc = "An improved laser emitter for rapidly creating and cauterizing precise surgical incisions." icon_state = "scalpel_laser2_on" toolspeed = 0.6 /obj/item/scalpel/laser/laser3 name = "laser scalpel" - desc = "A scalpel augmented with a directed laser. This one looks to be the pinnacle of precision energy cutlery!" + desc = "An advanced laser emitter for creating and cauterizing precise surgical incisions with extreme speed." icon_state = "scalpel_laser3_on" toolspeed = 0.4 @@ -179,7 +179,7 @@ /obj/item/circular_saw name = "circular saw" - desc = "For heavy duty cutting." + desc = "A sterilized medical saw for use in cutting through bone." icon = 'icons/obj/surgery.dmi' icon_state = "saw" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -211,6 +211,7 @@ //misc, formerly from code/defines/weapons.dm /obj/item/bonegel name = "bone gel" + desc = "A large bottle of fast-setting medical adhesive. There's more than enough inside to last the shift." icon = 'icons/obj/surgery.dmi' icon_state = "bone-gel" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -230,6 +231,7 @@ /obj/item/FixOVein name = "FixOVein" + desc = "An advanced medical device which uses an array of manipulators to reconnect and repair ruptured blood vessels." icon = 'icons/obj/surgery.dmi' icon_state = "fixovein" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -249,6 +251,7 @@ /obj/item/bonesetter name = "bone setter" + desc = "A stainless steel medical clamp used to reconnect fractured bones." icon = 'icons/obj/surgery.dmi' icon_state = "bonesetter" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -271,7 +274,7 @@ /obj/item/surgical_drapes name = "surgical drapes" - desc = "Nanotrasen brand surgical drapes provide optimal safety and infection control." + desc = "Apearature brand surgical drapes providing privacy and infection control." icon = 'icons/obj/surgery.dmi' icon_state = "surgical_drapes" w_class = WEIGHT_CLASS_SMALL diff --git a/config/example/config.toml b/config/example/config.toml index fedba7ae4a3..48884d6a092 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -67,12 +67,39 @@ enable_localhost_autoadmin = true # +VIEWRUNTIMES = Allows a player to view the runtimes of the server, but not use other debug verbs admin_ranks = [ # Format: {name = "My Rank", rights = ["+LIST", "+OF", "+RIGHTS"]} - {name = "Mentor", rights = ["+MENTOR"]}, - {name = "Trial Admin", rights = ["+ADMIN", "+BAN", "+STEALTH", "+REJUVINATE"]}, - {name = "Game Admin", rights = ["+ADMIN", "+BAN", "+STEALTH", "+REJUVINATE", "+DEBUG", "+BUILDMODE", "+EVENT", "+SERVER", "+POSSESS", "+PROCCALL", "+VAREDIT", "+SOUND", "+SPAWN"]}, - {name = "Head of Staff", rights = ["+EVERYTHING"]}, - {name = "Hosting Provider", rights = ["+EVERYTHING"]}, - {name = "Maintainers", rights = ["+EVERYTHING"]} + { name = "Mentor", rights = [ + "+MENTOR", + ] }, + { name = "Trial Admin", rights = [ + "+ADMIN", + "+BAN", + "+STEALTH", + "+REJUVINATE", + ] }, + { name = "Game Admin", rights = [ + "+ADMIN", + "+BAN", + "+STEALTH", + "+REJUVINATE", + "+DEBUG", + "+BUILDMODE", + "+EVENT", + "+SERVER", + "+POSSESS", + "+PROCCALL", + "+VAREDIT", + "+SOUND", + "+SPAWN", + ] }, + { name = "Head of Staff", rights = [ + "+EVERYTHING", + ] }, + { name = "Hosting Provider", rights = [ + "+EVERYTHING", + ] }, + { name = "Maintainers", rights = [ + "+EVERYTHING", + ] }, ] # List of people and the admin rank they are assigned to admin_assignments = [ @@ -82,18 +109,18 @@ admin_assignments = [ allow_admin_ooc_colour = true # Map of admin rank colours to their respective rank. Note you can use hex or colour name here. admin_rank_colour_map = [ - {name = "Head of Staff", colour = "#e74c3c"}, - {name = "Maintainer", colour = "#992d22"}, - {name = "Server Dev", colour = "#1abc9c"}, - {name = "Community Manager", colour = "#e91e63"}, - {name = "Game Admin", colour = "#238afa"}, - {name = "Trial Admin", colour = "#7fb6fc"}, - {name = "PR Reviewer", colour = "#c27c0e"}, - {name = "Mentor", colour = "#f1c40f"}, + { name = "Head of Staff", colour = "#e74c3c" }, + { name = "Maintainer", colour = "#992d22" }, + { name = "Server Dev", colour = "#1abc9c" }, + { name = "Community Manager", colour = "#e91e63" }, + { name = "Game Admin", colour = "#238afa" }, + { name = "Trial Admin", colour = "#7fb6fc" }, + { name = "PR Reviewer", colour = "#c27c0e" }, + { name = "Mentor", colour = "#f1c40f" }, ] # Map of common CIDs that should not be banned, plus their reasons common_cid_map = [ - {cid = "3923664137", reason = "Mass-Match related to Walmart branded prebuilt PCs"} + { cid = "3923664137", reason = "Mass-Match related to Walmart branded prebuilt PCs" }, ] @@ -131,7 +158,10 @@ ai_hologram = ["ckeyhere"] pai_holoform = ["ckeyhere"] # List of dictionary entries for ckeys with a custom IPC screean ipc_screens = [ - {ckey = "ckeyhere", screens = ["Icon State 1", "Icon State 2"]} + { ckey = "ckeyhere", screens = [ + "Icon State 1", + "Icon State 2", + ] }, ] @@ -145,7 +175,7 @@ ipc_screens = [ # Enable/disable the database on a whole sql_enabled = false # SQL version. If this is a mismatch, round start will be delayed -sql_version = 55 +sql_version = 56 # SQL server address. Can be an IP or DNS name sql_address = "127.0.0.1" # SQL server port @@ -171,20 +201,14 @@ async_thread_limit = 50 # All role IDs must be STRINGS as BYOND doesnt like ints that big enable_discord_webhooks = false # List of all webhooks for the primary feed (public channels) -main_webhook_urls = [ - "https://webhook.one", - "https://webhook.two" -] +main_webhook_urls = ["https://webhook.one", "https://webhook.two"] # List of all webhook URLs for the mentor feed (mentorhelps relay) mentor_webhook_urls = [ "https://mentor.webhook.one", - "https://mentor.webhook.two" + "https://mentor.webhook.two", ] # List of all webhook URLs for the admin feed (round alerts, ahelps, etc) -admin_webhook_urls = [ - "https://admin.webhook.one", - "https://admin.webhook.two" -] +admin_webhook_urls = ["https://admin.webhook.one", "https://admin.webhook.two"] # Role ID for the admin role on the discord. Set to "" to disable. # THESE MUST BOTH BE STRINGS. BYOND DOESNT LIKE NUMBERS THIS BIG admin_role_id = "" @@ -204,9 +228,9 @@ forward_all_ahelps = true # Disable this to disable all random events allow_random_events = true # Map of lower bounds for event delays. In minutes. -event_delay_lower_bounds = {mundane = 10, moderate = 30, major = 50} +event_delay_lower_bounds = { mundane = 10, moderate = 30, major = 50 } # Map of upper bounds for event delays. In minutes. -event_delay_upper_bounds = {mundane = 15, moderate = 45, major = 70} +event_delay_upper_bounds = { mundane = 15, moderate = 45, major = 70 } # Expected round length in minutes. Changes event weights expected_round_length = 120 # Initial delays for the first events firing off. If any of these are commented, a random value based on above thresholds is used. @@ -214,8 +238,8 @@ expected_round_length = 120 # Values are in minutes event_initial_delays = [ #{severity = "mundane", lower_bound = 10, upper_bound = 15}, - {severity = "moderate", lower_bound = 25, upper_bound = 40}, - {severity = "major", lower_bound = 55, upper_bound = 75}, + { severity = "moderate", lower_bound = 25, upper_bound = 40 }, + { severity = "major", lower_bound = 55, upper_bound = 75 }, ] @@ -229,20 +253,20 @@ event_initial_delays = [ antag_account_age_restrictions = false # Gamemode probabilities map for if you are using secret or random gamemode_probabilities = [ - {gamemode = "abduction", probability = 0}, - {gamemode = "changeling", probability = 3}, - {gamemode = "cult", probability = 3}, - {gamemode = "extend-a-traitormongous", probability = 2}, # Autotraitor - {gamemode = "extended", probability = 3}, - {gamemode = "nuclear", probability = 2}, - {gamemode = "raginmages", probability = 0}, - {gamemode = "revolution", probability = 0}, - {gamemode = "traitor", probability = 2}, - {gamemode = "traitorchan", probability = 3}, - {gamemode = "traitorvamp", probability = 3}, - {gamemode = "vampire", probability = 3}, - {gamemode = "wizard", probability = 2}, - {gamemode = "trifecta", probability = 3}, + { gamemode = "abduction", probability = 0 }, + { gamemode = "changeling", probability = 3 }, + { gamemode = "cult", probability = 3 }, + { gamemode = "extend-a-traitormongous", probability = 2 }, # Autotraitor + { gamemode = "extended", probability = 3 }, + { gamemode = "nuclear", probability = 2 }, + { gamemode = "raginmages", probability = 0 }, + { gamemode = "revolution", probability = 0 }, + { gamemode = "traitor", probability = 2 }, + { gamemode = "traitorchan", probability = 3 }, + { gamemode = "traitorvamp", probability = 3 }, + { gamemode = "vampire", probability = 3 }, + { gamemode = "wizard", probability = 2 }, + { gamemode = "trifecta", probability = 3 }, ] # Do we want the amount of traitors to scale with population? traitor_scaling = true @@ -409,44 +433,44 @@ enable_job_amount_overrides = true # Job slot amount map. These are overrides. If you dont specify a value here, the code will be used as default. -1 is infinite job_slot_amounts = [ # Commmand - {name = "Captain", lowpop = 1, highpop = 1}, - {name = "Head of Personnel", lowpop = 1, highpop = 1}, - {name = "Head of Security", lowpop = 1, highpop = 1}, - {name = "Chief Engineer", lowpop = 1, highpop = 1}, - {name = "Research Director", lowpop = 1, highpop = 1}, - {name = "Chief Medical Officer", lowpop = 1, highpop = 1}, + { name = "Captain", lowpop = 1, highpop = 1 }, + { name = "Head of Personnel", lowpop = 1, highpop = 1 }, + { name = "Head of Security", lowpop = 1, highpop = 1 }, + { name = "Chief Engineer", lowpop = 1, highpop = 1 }, + { name = "Research Director", lowpop = 1, highpop = 1 }, + { name = "Chief Medical Officer", lowpop = 1, highpop = 1 }, # Engineering - {name = "Life Support Specialist", lowpop = 3, highpop = 4}, - {name = "Station Engineer", lowpop = 5, highpop = 6}, + { name = "Life Support Specialist", lowpop = 3, highpop = 4 }, + { name = "Station Engineer", lowpop = 5, highpop = 6 }, # Medical - {name = "Chemist", lowpop = 2, highpop = 2}, - {name = "Geneticist", lowpop = 2, highpop = 2}, - {name = "Medical Doctor", lowpop = 5, highpop = 6}, - {name = "Virologist", lowpop = 1, highpop = 1}, + { name = "Chemist", lowpop = 2, highpop = 2 }, + { name = "Geneticist", lowpop = 2, highpop = 2 }, + { name = "Medical Doctor", lowpop = 5, highpop = 6 }, + { name = "Virologist", lowpop = 1, highpop = 1 }, # Science - {name = "Roboticist", lowpop = 2, highpop = 2}, - {name = "Scientist", lowpop = 6, highpop = 7}, + { name = "Roboticist", lowpop = 2, highpop = 2 }, + { name = "Scientist", lowpop = 6, highpop = 7 }, # Security - {name = "Detective", lowpop = 1, highpop = 1}, - {name = "Security Officer", lowpop = 8, highpop = 9}, - {name = "Warden", lowpop = 1, highpop = 1}, - {name = "Internal Affairs Agent", lowpop = 2, highpop = 2}, + { name = "Detective", lowpop = 1, highpop = 1 }, + { name = "Security Officer", lowpop = 8, highpop = 9 }, + { name = "Warden", lowpop = 1, highpop = 1 }, + { name = "Internal Affairs Agent", lowpop = 2, highpop = 2 }, # Service - {name = "Bartender", lowpop = 1, highpop = 1}, - {name = "Botanist", lowpop = 2, highpop = 2}, - {name = "Chaplain", lowpop = 1, highpop = 1}, - {name = "Chef", lowpop = 1, highpop = 1}, - {name = "Janitor", lowpop = 1, highpop = 2}, - {name = "Librarian", lowpop = 1, highpop = 1}, + { name = "Bartender", lowpop = 1, highpop = 1 }, + { name = "Botanist", lowpop = 2, highpop = 2 }, + { name = "Chaplain", lowpop = 1, highpop = 1 }, + { name = "Chef", lowpop = 1, highpop = 1 }, + { name = "Janitor", lowpop = 1, highpop = 2 }, + { name = "Librarian", lowpop = 1, highpop = 1 }, # Cargo/Supply - {name = "Quartermaster", lowpop = 1, highpop = 1}, - {name = "Shaft Miner", lowpop = 6, highpop = 6}, - {name = "Cargo Technician", lowpop = 3, highpop = 4}, + { name = "Quartermaster", lowpop = 1, highpop = 1 }, + { name = "Shaft Miner", lowpop = 6, highpop = 6 }, + { name = "Cargo Technician", lowpop = 3, highpop = 4 }, # Silicon - {name = "AI", lowpop = 1, highpop = 1}, - {name = "Cyborg", lowpop = 1, highpop = 1}, + { name = "AI", lowpop = 1, highpop = 1 }, + { name = "Cyborg", lowpop = 1, highpop = 1 }, # Misc - {name = "Assistant", lowpop = -1, highpop = -1}, + { name = "Assistant", lowpop = -1, highpop = -1 }, ] @@ -689,6 +713,7 @@ active_lava_ruins = [ "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_survivalpod.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ufo_crash.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_watcher_grave.dmm", @@ -815,11 +840,11 @@ non_repeating_maps = true # - "Random" = no vote, map is random # If you dont enter one correctly, it will whine on startup map_vote_day_types = [ - { day_number = 1, rotation_type = "Vote" }, # Monday - { day_number = 2, rotation_type = "Random" }, # Tuesday - { day_number = 3, rotation_type = "Vote" }, # Wednesday - { day_number = 4, rotation_type = "Random" }, # Thursday - { day_number = 5, rotation_type = "Vote" }, # Friday + { day_number = 1, rotation_type = "Vote" }, # Monday + { day_number = 2, rotation_type = "Random" }, # Tuesday + { day_number = 3, rotation_type = "Vote" }, # Wednesday + { day_number = 4, rotation_type = "Random" }, # Thursday + { day_number = 5, rotation_type = "Vote" }, # Friday { day_number = 6, rotation_type = "Nodupes" }, # Saturday { day_number = 7, rotation_type = "Nodupes" }, # Sunday ] diff --git a/icons/_nanomaps/CereStation_nanomap_z1.png b/icons/_nanomaps/CereStation_nanomap_z1.png index 2563ef75b93..99ec3d7bbb5 100644 Binary files a/icons/_nanomaps/CereStation_nanomap_z1.png and b/icons/_nanomaps/CereStation_nanomap_z1.png differ diff --git a/icons/_nanomaps/Cyberiad_nanomap_z1.png b/icons/_nanomaps/Cyberiad_nanomap_z1.png index 621fa17f543..c7d9da2ba13 100644 Binary files a/icons/_nanomaps/Cyberiad_nanomap_z1.png and b/icons/_nanomaps/Cyberiad_nanomap_z1.png differ diff --git a/icons/_nanomaps/Delta_nanomap_z1.png b/icons/_nanomaps/Delta_nanomap_z1.png index 5c13b4e1761..c1fba40f0da 100644 Binary files a/icons/_nanomaps/Delta_nanomap_z1.png and b/icons/_nanomaps/Delta_nanomap_z1.png differ diff --git a/icons/_nanomaps/MetaStation_nanomap_z1.png b/icons/_nanomaps/MetaStation_nanomap_z1.png index 767c69c695c..e1d4c00fcb7 100644 Binary files a/icons/_nanomaps/MetaStation_nanomap_z1.png and b/icons/_nanomaps/MetaStation_nanomap_z1.png differ diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 7746a3d06d0..ca835f75288 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/mob_hunt.dmi b/icons/effects/mob_hunt.dmi deleted file mode 100644 index 1eea83a9afa..00000000000 Binary files a/icons/effects/mob_hunt.dmi and /dev/null differ diff --git a/icons/mecha/mecha.dmi b/icons/mecha/mecha.dmi index 9d5db73c394..6c058ef9416 100644 Binary files a/icons/mecha/mecha.dmi and b/icons/mecha/mecha.dmi differ diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index f8626a6d6bb..d0d67fc81ae 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/icons/mob/inhands/equipment/custodial_lefthand.dmi b/icons/mob/inhands/equipment/custodial_lefthand.dmi index 884b23465cb..c4f2e189a21 100644 Binary files a/icons/mob/inhands/equipment/custodial_lefthand.dmi and b/icons/mob/inhands/equipment/custodial_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/custodial_righthand.dmi b/icons/mob/inhands/equipment/custodial_righthand.dmi index 8ddb7703cf6..4db565e94ba 100644 Binary files a/icons/mob/inhands/equipment/custodial_righthand.dmi and b/icons/mob/inhands/equipment/custodial_righthand.dmi differ diff --git a/icons/mob/inhands/weapons_lefthand.dmi b/icons/mob/inhands/weapons_lefthand.dmi index a5c22c4cef8..6815485c27b 100644 Binary files a/icons/mob/inhands/weapons_lefthand.dmi and b/icons/mob/inhands/weapons_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons_righthand.dmi b/icons/mob/inhands/weapons_righthand.dmi index afcbe22ddcc..612365aed42 100644 Binary files a/icons/mob/inhands/weapons_righthand.dmi and b/icons/mob/inhands/weapons_righthand.dmi differ diff --git a/icons/mob/screen_scope.dmi b/icons/mob/screen_scope.dmi new file mode 100644 index 00000000000..03ca5665dbf Binary files /dev/null and b/icons/mob/screen_scope.dmi differ diff --git a/icons/obj/3x3.dmi b/icons/obj/3x3.dmi new file mode 100644 index 00000000000..07a0213aa93 Binary files /dev/null and b/icons/obj/3x3.dmi differ diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi index ba5ee59349d..48de9bc1858 100644 Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ diff --git a/icons/obj/computer.dmi b/icons/obj/computer.dmi index 5b56dd841d3..46b03c24226 100644 Binary files a/icons/obj/computer.dmi and b/icons/obj/computer.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index fe9c40361f1..2bcc8d2e604 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/obj/nuclearbomb.dmi b/icons/obj/nuclearbomb.dmi index bb86ae4a618..ad6bc4d7efc 100644 Binary files a/icons/obj/nuclearbomb.dmi and b/icons/obj/nuclearbomb.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 6bce8d4a243..6da7f531565 100644 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi index 9c265a8f5e2..a41f594dfaf 100755 Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ diff --git a/icons/turf/decals.dmi b/icons/turf/decals.dmi index 52372c44c16..91d9f0f96fc 100644 Binary files a/icons/turf/decals.dmi and b/icons/turf/decals.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 729792edc29..df48d1dcdd7 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -21,6 +21,11 @@ menu "menu" command = "SS-Info-Breakdown" category = "&File" is-disabled = true + elem "profilecode" + name = "&Profile Code" + command = ".profile" + category = "&File" + is-disabled = true elem name = "&Quit" command = ".quit" diff --git a/paradise.dme b/paradise.dme index 427bca5bcd2..8f0b4deab90 100644 --- a/paradise.dme +++ b/paradise.dme @@ -84,13 +84,13 @@ #include "code\__DEFINES\martial_arts.dm" #include "code\__DEFINES\MC.dm" #include "code\__DEFINES\mecha_defines.dm" +#include "code\__DEFINES\mecha_hides.dm" #include "code\__DEFINES\medal.dm" #include "code\__DEFINES\misc_defines.dm" #include "code\__DEFINES\mob_defines.dm" #include "code\__DEFINES\mod.dm" #include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\muzzle_flash.dm" -#include "code\__DEFINES\nanomob_defines.dm" #include "code\__DEFINES\newscaster_defines.dm" #include "code\__DEFINES\particle_defines.dm" #include "code\__DEFINES\pda.dm" @@ -135,6 +135,7 @@ #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\wires_defines.dm" #include "code\__DEFINES\zlevel_defines.dm" +#include "code\__DEFINES\zoom.dm" #include "code\__DEFINES\dcs\dcs_flags.dm" #include "code\__DEFINES\dcs\dcs_helpers.dm" #include "code\__DEFINES\dcs\signals.dm" @@ -294,7 +295,6 @@ #include "code\controllers\subsystem\SSmachinery.dm" #include "code\controllers\subsystem\SSmetrics.dm" #include "code\controllers\subsystem\SSmobs.dm" -#include "code\controllers\subsystem\SSnano_mob_hunter.dm" #include "code\controllers\subsystem\SSnightshift.dm" #include "code\controllers\subsystem\SSnpcpool.dm" #include "code\controllers\subsystem\SSoverlays.dm" @@ -372,6 +372,7 @@ #include "code\datums\mixed.dm" #include "code\datums\movement_detector.dm" #include "code\datums\mutable_appearance.dm" +#include "code\datums\particles.dm" #include "code\datums\pathfinding_mover.dm" #include "code\datums\periodic_news.dm" #include "code\datums\pipe_datums.dm" @@ -420,6 +421,7 @@ #include "code\datums\components\persistent_overlay.dm" #include "code\datums\components\proximity_monitor.dm" #include "code\datums\components\radioactive.dm" +#include "code\datums\components\scope.dm" #include "code\datums\components\shielded.dm" #include "code\datums\components\slippery.dm" #include "code\datums\components\spawner.dm" @@ -989,6 +991,7 @@ #include "code\game\objects\effects\spawners\windowspawner.dm" #include "code\game\objects\effects\temporary_visuals\clockcult.dm" #include "code\game\objects\effects\temporary_visuals\cult_visuals.dm" +#include "code\game\objects\effects\temporary_visuals\explosion_temp_visuals.dm" #include "code\game\objects\effects\temporary_visuals\misc_visuals.dm" #include "code\game\objects\effects\temporary_visuals\muzzle_flashes.dm" #include "code\game\objects\effects\temporary_visuals\temporary_visual.dm" @@ -1073,6 +1076,7 @@ #include "code\game\objects\items\mountable_frames\mountables.dm" #include "code\game\objects\items\mountable_frames\newscaster_frame.dm" #include "code\game\objects\items\robot\ai_upgrades.dm" +#include "code\game\objects\items\robot\cyborg_gripper.dm" #include "code\game\objects\items\robot\robot_items.dm" #include "code\game\objects\items\robot\robot_parts.dm" #include "code\game\objects\items\robot\robot_upgrades.dm" @@ -1364,6 +1368,7 @@ #include "code\modules\admin\mute.dm" #include "code\modules\admin\outfits.dm" #include "code\modules\admin\player_panel.dm" +#include "code\modules\admin\reagents_editor.dm" #include "code\modules\admin\secrets.dm" #include "code\modules\admin\sql_notes.dm" #include "code\modules\admin\topic.dm" @@ -1491,11 +1496,6 @@ #include "code\modules\arcade\claw_game.dm" #include "code\modules\arcade\prize_counter.dm" #include "code\modules\arcade\prize_datums.dm" -#include "code\modules\arcade\mob_hunt\battle_computer.dm" -#include "code\modules\arcade\mob_hunt\mob_avatar.dm" -#include "code\modules\arcade\mob_hunt\mob_cards.dm" -#include "code\modules\arcade\mob_hunt\mob_datums.dm" -#include "code\modules\arcade\mob_hunt\mob_type_datums.dm" #include "code\modules\assembly\assebmly_holder.dm" #include "code\modules\assembly\assembly.dm" #include "code\modules\assembly\assembly_helpers.dm" @@ -1521,7 +1521,6 @@ #include "code\modules\asset_cache\assets\asset_emoji.dm" #include "code\modules\asset_cache\assets\asset_jquery.dm" #include "code\modules\asset_cache\assets\asset_materials.dm" -#include "code\modules\asset_cache\assets\asset_mob_hunt.dm" #include "code\modules\asset_cache\assets\asset_nanomap.dm" #include "code\modules\asset_cache\assets\asset_orbit_icons.dm" #include "code\modules\asset_cache\assets\asset_panels.dm" @@ -1662,6 +1661,7 @@ #include "code\modules\clothing\glasses\glasses.dm" #include "code\modules\clothing\glasses\hudglasses.dm" #include "code\modules\clothing\glasses\hudgoggles.dm" +#include "code\modules\clothing\glasses\tajblind.dm" #include "code\modules\clothing\gloves\boxing_gloves.dm" #include "code\modules\clothing\gloves\colored_gloves.dm" #include "code\modules\clothing\gloves\misc_gloves.dm" @@ -2014,6 +2014,7 @@ #include "code\modules\martial_arts\combos\judo\armbar.dm" #include "code\modules\martial_arts\combos\judo\discombobulate.dm" #include "code\modules\martial_arts\combos\judo\eyepoke.dm" +#include "code\modules\martial_arts\combos\judo\goldenblast.dm" #include "code\modules\martial_arts\combos\judo\judothrow.dm" #include "code\modules\martial_arts\combos\judo\wheelthrow.dm" #include "code\modules\martial_arts\combos\krav_maga\leg_sweep.dm" @@ -2227,6 +2228,7 @@ #include "code\modules\mob\living\silicon\ai\ai_say.dm" #include "code\modules\mob\living\silicon\ai\ai_update_status.dm" #include "code\modules\mob\living\silicon\ai\latejoin.dm" +#include "code\modules\mob\living\silicon\ai\ai_verbs\botcall.dm" #include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm" #include "code\modules\mob\living\silicon\ai\freelook\chunk.dm" #include "code\modules\mob\living\silicon\ai\freelook\eye.dm" @@ -2496,7 +2498,6 @@ #include "code\modules\pda\core_apps.dm" #include "code\modules\pda\messenger.dm" #include "code\modules\pda\messenger_plugins.dm" -#include "code\modules\pda\mob_hunt_game_app.dm" #include "code\modules\pda\nanobank.dm" #include "code\modules\pda\PDA.dm" #include "code\modules\pda\pda_tgui.dm" @@ -2718,6 +2719,7 @@ #include "code\modules\shuttle\dock_generator.dm" #include "code\modules\shuttle\emergency.dm" #include "code\modules\shuttle\ert_shuttle.dm" +#include "code\modules\shuttle\lance_docking_targeter.dm" #include "code\modules\shuttle\navigation_computer.dm" #include "code\modules\shuttle\on_move.dm" #include "code\modules\shuttle\ripple.dm" @@ -2748,6 +2750,7 @@ #include "code\modules\station_goals\secondary\botany\kudzu_goal.dm" #include "code\modules\station_goals\secondary\kitchen\random_bulk_condiment.dm" #include "code\modules\station_goals\secondary\kitchen\random_bulk_food.dm" +#include "code\modules\station_goals\secondary\kitchen\variety_food.dm" #include "code\modules\station_goals\secondary\medical\random_bulk_medicine.dm" #include "code\modules\station_goals\secondary\medical\variety_medicine.dm" #include "code\modules\station_goals\secondary\science\random_bulk_chemical.dm" diff --git a/sound/weapons/goldenblast.ogg b/sound/weapons/goldenblast.ogg new file mode 100644 index 00000000000..90dd9a00405 Binary files /dev/null and b/sound/weapons/goldenblast.ogg differ diff --git a/sound/weapons/scope.ogg b/sound/weapons/scope.ogg new file mode 100644 index 00000000000..37d70b6ff4c Binary files /dev/null and b/sound/weapons/scope.ogg differ diff --git a/strings/sillytips.txt b/strings/sillytips.txt index abf295ab888..5977b99b19b 100644 --- a/strings/sillytips.txt +++ b/strings/sillytips.txt @@ -29,4 +29,5 @@ Absolutely nothing unusual will happen this shift. Promise. Send help. Trapped in tip writing factory. There is no such thing as a cow level. HONK. -Solars probably gives radiation poisoning or something, considering the other power sources are deadly in their own ways. \ No newline at end of file +Solars probably give radiation poisoning or something, considering the other power sources are deadly in their own ways. +Nanotrasen would like to remind you that the popular "Deathsquad" show is completely fictional. The Deathsquad is not real. Making any suggestion to the contrary is grounds for immediate termination. \ No newline at end of file diff --git a/strings/tips.txt b/strings/tips.txt index 93aa54aa759..39a692379c5 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -1,13 +1,13 @@ Space map levels' connections are randomized between rounds, but are otherwise kept consistent in the same round. You can catch thrown items by toggling on your throw mode with an empty hand active. -To crack the safe in the vault, use a stethoscope or thermal drill. +To crack the safe in the vault, use a stethoscope or thermal drill. You can also steal the combination paper from the captain's office, if they didn't secure it. You can climb onto a table by dragging yourself onto one. This takes some time. Clicking on a table that someone else is climbing onto will knock them down. You can drag other players onto yourself to open the strip menu, letting you remove their equipment or force them to wear something. Note that exosuits or helmets will block your access to the clothing beneath them, and that certain items take longer to strip or put on than others. Clicking on a windoor rather than bumping into it will keep it open. You can click it again to close it. You can spray a fire extinguisher, throw items, or fire a gun while floating through space to change your direction. Simply fire in the opposite direction of where you want to go. You can change the control scheme by pressing tab. One uses WASD for movement, while the other uses the arrow keys. Keep in mind that hotkeys are also changed with this. Firesuits and winter coats offer mild protection from the cold, allowing you to spend longer periods of time near breaches and space than if wearing nothing at all. -Glass shards can be welded to make glass, and metal rods can be welded to make metal. Ores can be welded too, but this takes a lot of fuel. +Glass shards can be welded to make glass, and metal rods and tiles can be welded to make metal. Ores can be welded too, but this takes a lot of fuel. If you need to drag multiple people either to safety or to space, bring a locker over and stuff them all in before hauling them off. You can grab someone by clicking on them with the grab intent, then upgrade the grab by clicking on the grab itself. An aggressive grab will allow you to place them on a table by clicking on it, or throw them by toggling on throwing. Holding alt and left clicking a tile will allow you to see its contents in the top right window panel, which is much faster than right clicking. @@ -52,13 +52,13 @@ As a Scientist, you can disable anomalies by scanning them with an analyzer, the As a Scientist, researchable stock parts can seriously improve the efficiency and speed of machines around the station. In some cases, it can even unlock new functions. As a Roboticist, keep an ear out for anomaly announcements. If you get your hands on a bluespace anomaly core, you can build a Phazon mech! As a Roboticist, you can repair your cyborgs with a welding tool. If they have taken burn damage, you can remove their battery, expose the wiring with a screwdriver and replace their wires with a cable coil. -As a Roboticist, you can reset a cyborg's module by cutting and mending the reset wire with a wire cutter or using a cyborg reset module. +As a Roboticist, you can use a multitool on an empty cyborg shell to alter various settings, including whether it will connect to the AI. As a Roboticist, you can augment people with cyborg limbs. Augmented limbs can easily be repaired with cables and welders. As the AI, you can click on people's names to look at them. This only works if there are cameras that can see them, they aren't wearing agent IDs, or aren't using digital camouflage as changelings. As the AI, you can quickly open and close doors by holding shift while clicking them, bolt them when holding ctrl, and even shock them while holding alt. As the AI, you can take pictures with your camera and upload them to newscasters. As a Cyborg, choose your module carefully, as only a cyborg reset module will let you repick it. -As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes can easily stunlock you and you cannot do any precision work as you lack hands. +As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes can easily stunlock you and there are many tasks you cannot perform as your grippers will not allow you to. As a Cyborg, you are impervious to fires and heat. If you are rogue, you can release plasma fires everywhere and walk through them without a care in the world! As a Cyborg, you are extremely vulnerable to EMPs as EMPs both stun you and damage you. The ion rifle in the armory or a traitor with an EMP kit can kill you in seconds. As an Engineering Cyborg, you can attach air alarm/fire alarm/APC frames to walls by using your magnetic gripper. @@ -75,6 +75,7 @@ As an Engineer, you can repair windows by using a welding tool on them while on As an Engineer, you can lock APCs, fire alarms, emitters, and radiation collectors using your ID card to prevent others from disabling them. As an Engineer, don't underestimate the humble P.A.C.M.A.N. generators. With upgraded parts, a couple units working in tandem are sufficient to take over for an exploded engine or shattered solars. As an Engineer, you can pry open secure storage blast doors by turning off the secure storage APC's enviroment power channel. +As an Engineer, you can set up the SMES units before working on the engine. This will stop the station from running out of power before the engine is online. As an Atmospheric Technician, look into replacing your gas pumps with volumetric gas pumps, as those move air in flat numerical amounts, rather than percentages which leave trace gases. As an Atmospheric Technician, you are better suited to fighting fires than anyone else. As such, you have access to better firesuits, backpack firefighter tanks, and a completely heat and fire proof hardsuit. As an Atmospheric Technician, your backpack firefighter tank can launch cryofrost. This resin will extinguish fires and very quickly; it's ideal for plasma fires! @@ -112,7 +113,7 @@ As a Botanist, you can combine production trait chemicals just like a Chemist. C As the Chef, you can create a very wide variety of food with the crafting menu. You can find it by looking for the hammer icon near your intents. As the Chef, you can rename your custom made food with a pen. As the Chef, if you are low on ingredients, consider making something that has several servings to last longer among the crew. -As the Bartender, you can use a circular saw on your shotgun to make it easier to store. +As the Bartender, you can use a circular saw on your shotgun to make it easier to store. Remember to unload it first! As a Janitor, if someone steals your janicart, you can instead use your space cleaner spray, grenades, water sprayer or order another from Cargo. As a Janitor, mousetraps can be used to create bombs or booby-trap containers. As the Librarian, be sure to keep the shelves stocked and the library clean for crew. @@ -137,6 +138,7 @@ As a Nuclear Operative, you might end up in a situation where the AI has bolted As a Monkey, you can still wear a few human items, such as backpacks, gas masks, and hats, and still have two free hands. As the Malfunctioning AI, you can shunt to an APC if the situation gets bad. As the Malfunctioning AI, you should either order your cyborgs to dismantle the robotics console or blow it up yourself in order to protect them. +As the Malfunctioning AI, you start with access to the syndicate comms frequency. You can listen in on traitor communications, or reach out and coordinate with them. As an Alien, your melee prowess is unmatched, but your ranged abilities are sorely lacking. Make use of corners to force a melee confrontation! As an Alien, you take double damage from all burn attacks, such as lasers, welding tools, and fires. Furthermore, fire can destroy your resin and eggs. Expose areas to space to starve away any flamethrower fires before they can do damage! As an Alien, resin floors not only regenerate your plasma supply, but also passively heal you. Fight on resin floors to gain a home turf advantage! @@ -161,6 +163,7 @@ As a Wizard, the fireball spell performs very poorly at close range, as it can e As a Wizard, summoning guns will give everyone anything from a floral somatoray to a pulse rifle. Use at your own risk! As a Wizard, the staff of chaos can fire any type of bolts from the magical wands. This can range from bolts of instant death to healing or reviving someone. As a Wizard, most spells become unusable if you are not wearing your robe, hat, and sandals. +As a Wizard, don't forget to grab Mugwort before leaving your den, it's a very useful medicine! As an Abductor, you can select where your victims will be sent on the ship control console. As an Abductor Agent, the combat mode vest has much higher resistance to every kind of weapon, and your helmet prevents the AI from tracking you. As an Abductor, the baton can cycle between four modes: stun, sleep, cuff and probe. @@ -180,11 +183,14 @@ As a Terror Spider, protect the queen at all cost! As a Terror Spider, don't forget you can move your nest if the crew is pressuring you too badly. As a Terror Spider, try putting webs on white floor tiles, they are much harder to see there. As a Terror Spider, sometimes quickly pulling an enemy into a web can ensure victory in melee combat. +Remote signalers are extremely versatile. They can be used in bombs, hacking, counteracting anomalies, and much more. Get creative! +Need to perform surgery? No surgery kit? No worries! You can use a wide variety of improvised tools to perform ghetto surgery! For example, using a wrench as a stand-in for a bone setter, or a cigarette as a cautery. You can even use alcohol as a makeshift painkiller. Just be aware that these tools may not work as well as proper ones. +If you examine something twice in quick succession, you will perform an extended examination. Many items have extended descriptions that give you more information about the world. You can swap floor tiles by holding a crowbar in one hand and a stack of tiles in the other. When hacking doors, cutting and mending a "test light wire" will restore power to the door. When crafting most items, you can either manually combine parts or use the crafting menu. Suit storage units not only remove blood and dirt from clothing, but also radiation! -Sleeping in a bed can heal minor amounts of brute and burn damage. +Sleeping in a bed can heal minor amounts of brute and burn damage. It can also cure the common cold. The Experimentor has a chance to spawn hostile mobs. Be ready to run for your life when using it. Space ruins can contain all kinds of interesting goodies, even a wand that can raise the dead! Having a mindshield, or having an agent ID card will make officer Beepsky consider you less arrest-worthy. @@ -193,3 +199,4 @@ Blob structures take half damage from brute damage. Use lasers. You can hide paper in vents, but you have to use a screwdriver to open it first. While the Standard Operating Procedures aren't fully rules, they are there for safety and professional reasons. Killing the Wizard usually ends the round, unless they are a lich or Space Wizard Federation is RAGING. +The admins are not omnipotent and can miss things that happen during the chaos of a round. If someone is breaking the rules, you can press F1 or use the Ahelp verb to notify them. Even if there are no admins online, the Ahelp will be recorded. It also gets sent to a special channel on the Paradise Discord. diff --git a/tgui/packages/tgui/index.js b/tgui/packages/tgui/index.js index ab86b58ef1a..2496b2c4961 100644 --- a/tgui/packages/tgui/index.js +++ b/tgui/packages/tgui/index.js @@ -20,6 +20,7 @@ import './styles/themes/securestorage.scss'; import './styles/themes/security.scss'; import './styles/themes/syndicate.scss'; import './styles/themes/nologo.scss'; +import './styles/themes/noticeboard.scss'; import { perf } from 'common/perf'; import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; diff --git a/tgui/packages/tgui/interfaces/BotCall.js b/tgui/packages/tgui/interfaces/BotCall.js new file mode 100644 index 00000000000..98c0bc60400 --- /dev/null +++ b/tgui/packages/tgui/interfaces/BotCall.js @@ -0,0 +1,129 @@ +import { useBackend, useLocalState } from '../backend'; +import { Box, Button, Stack, Table, Tabs } from '../components'; +import { Window } from '../layouts'; + +const BotStatus = (mode) => { + const statusMap = [ + { modes: [0], label: 'Idle', color: 'green' }, + { modes: [1, 2, 3], label: 'Arresting', color: 'yellow' }, + { modes: [4, 5], label: 'Patrolling', color: 'average' }, + { modes: [6, 11], label: 'Responding', color: 'green' }, + { modes: [12], label: 'Delivering Cargo', color: 'blue' }, + { modes: [13], label: 'Returning Home', color: 'blue' }, + { modes: [7, 14, 15, 16, 17, 18, 19], label: 'Working', color: 'blue' }, + ]; + + const matchedStatus = statusMap.find((mapping) => + mapping.modes.includes(mode) + ); + + return {matchedStatus.label} ; +}; + +export const BotCall = (props, context) => { + const { act, data } = useBackend(context); + const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0); + const botNames = { + 0: 'Security', + 1: 'Medibot', + 2: 'Cleanbot', + 3: 'Floorbot', + 4: 'Mule', + 5: 'Honkbot', + }; + const decideTab = (index) => { + return botNames[index] ? ( + + ) : ( + 'This should not happen. Report on Paradise Github' + ); + }; + + return ( + + + + + + {Array.from({ length: 6 }).map((_, index) => ( + setTabIndex(index)} + > + {botNames[index]} + + ))} + + + {decideTab(tabIndex)} + + + + ); +}; + +const BotExists = (props, context) => { + const { act, data } = useBackend(context); + const { bots } = data; + if (bots[props.model] !== undefined) { + return ; + } else { + return ; + } +}; + +const NoBot = (props, context) => { + const { act, data } = useBackend(context); + return ( + + + No {[props.model]} detected + + + ); +}; + +const MapBot = (props, context) => { + const { act, data } = useBackend(context); + const { bots } = data; + + return ( + + +

Name

Status

Location

Control

[Bot.hacked ? "(!) [Bot.name]" : Bot.name] ([Bot.model])[Bot.on ? "[Bot.mode ? "[ Bot.mode_name[Bot.mode] ]": "Idle"]" : "Inactive"][bot_area.name]InterfaceCall
+ + Name + Model + Status + Location + Interface + Call + + {bots[props.model].map((bot) => ( + + {bot.name} + {bot.model} + + {bot.on ? BotStatus(bot.status) : Off} + + {bot.location} + +
+ + + ); +}; diff --git a/tgui/packages/tgui/interfaces/CommunicationsComputer.js b/tgui/packages/tgui/interfaces/CommunicationsComputer.js index 4cb4eacabaf..9563fdc3136 100644 --- a/tgui/packages/tgui/interfaces/CommunicationsComputer.js +++ b/tgui/packages/tgui/interfaces/CommunicationsComputer.js @@ -365,14 +365,6 @@ const PlayerPage = (props, context) => { onClick={() => act('messagelist')} /> - -