diff --git a/.gitignore b/.gitignore index 02f0c8cf790..9a9bbe0aafd 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ data/ /_maps/map_files/backup/* /_maps/map_files/**/backup/* /_maps/map_files/**/*.dmm.backup +/_maps/quicksave/* /nano/debug.html *.db stddef.dm diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index dd54aea2e92..ec34b6632f3 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -249,7 +249,7 @@ CREATE TABLE `player` ( `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', - `lastchangelog` varchar(32) NOT NULL, + `lastchangelog` varchar(32) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 453554f5c69..b5115a93caf 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -249,7 +249,7 @@ CREATE TABLE `SS13_player` ( `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', - `lastchangelog` varchar(32) NOT NULL, + `lastchangelog` varchar(32) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/_maps/__MAP_DEFINES.dm b/_maps/__MAP_DEFINES.dm new file mode 100644 index 00000000000..be9889b91e7 --- /dev/null +++ b/_maps/__MAP_DEFINES.dm @@ -0,0 +1,13 @@ + #define CROSSLINKED 2 + #define SELFLOOPING 1 + #define UNAFFECTED 0 + #define MAIN_STATION "Main Station" + #define CENTCOMM "CentComm" + #define TELECOMMS "Telecomms Satellite" + #define DERELICT "Derelicted Station" + #define MINING "Mining Asteroid" + #define CONSTRUCTION "Construction Area" + #define EMPTY_AREA "Empty Area" + #define EMPTY_AREA_2 "Empty Area 2" + #define AWAY_MISSION "Away Mission" + #define AWAY_MISSION_LIST list(AWAY_MISSION = UNAFFECTED) diff --git a/_maps/cyberiad.dm b/_maps/cyberiad.dm index 98ba7cf21f2..a2f78f9d26c 100644 --- a/_maps/cyberiad.dm +++ b/_maps/cyberiad.dm @@ -24,9 +24,10 @@ z7 = empty #define MAP_FILE "cyberiad.dmm" #define MAP_NAME "NSS Cyberiad" + #define MAP_TRANSITION_CONFIG list(MAIN_STATION = CROSSLINKED, CENTCOMM = SELFLOOPING, TELECOMMS = CROSSLINKED, CONSTRUCTION = CROSSLINKED, MINING = CROSSLINKED, DERELICT = CROSSLINKED, EMPTY_AREA = CROSSLINKED) #elif !defined(MAP_OVERRIDE) #warn a map has already been included, ignoring Cyberiad. -#endif \ No newline at end of file +#endif diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm index f435d880508..af126988b77 100644 --- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm +++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm @@ -151,7 +151,7 @@ "acU" = (/obj/item/weapon/soap/nanotrasen,/obj/item/weapon/bikehorn/rubberducky,/obj/machinery/shower{dir = 4},/obj/structure/cable/yellow{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/security/prison) "acV" = (/obj/structure/window/reinforced{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/sink/kitchen{desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; name = "old sink"; pixel_y = 28},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/security/prison) "acW" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/item/weapon/twohanded/required/kirbyplants{tag = "icon-plant-13"; icon_state = "plant-13"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) -"acX" = (/obj/structure/table,/obj/item/weapon/folder,/obj/item/weapon/paper/hydroponics,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/item/weapon/pen,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) +"acX" = (/obj/structure/table,/obj/item/weapon/folder,/obj/item/weapon/paper/hydroponics,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/item/weapon/pen,/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) "acY" = (/obj/structure/table,/obj/machinery/computer/library/public,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) "acZ" = (/obj/machinery/computer/arcade,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) "ada" = (/obj/machinery/camera{c_tag = "Prison Chamber"; network = list("SS13","Prison")},/obj/item/device/radio/intercom/locked/prison{dir = 2; name = "Prison Intercom (General)"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/plasteel,/area/security/prison) @@ -279,7 +279,7 @@ "afs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/stool/bed/chair/office/dark{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/prison/solitary{name = "Prisoner Education Chamber"}) "aft" = (/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/prison/solitary{name = "Prisoner Education Chamber"}) "afu" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/sink/kitchen{desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; name = "old sink"; pixel_y = 28},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 2; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/prison/solitary{name = "Prisoner Education Chamber"}) -"afv" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/power/apc{cell_type = 2500; dir = 1; name = "Prisoner Education Chamber APC"; pixel_y = 24},/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/obj/item/weapon/storage/backpack/duffel/security{contents = newlist(/obj/item/weapon/scalpel,/obj/item/weapon/hemostat,/obj/item/weapon/retractor,/obj/item/weapon/cautery,/obj/item/weapon/circular_saw,/obj/item/weapon/surgical_drapes,/obj/item/clothing/mask/surgical); desc = "A large dufflebag for holding extra supplies - this one has a material inlay with space for various sharp-looking tools."; name = "dufflebag"; pixel_y = 5},/obj/item/clothing/mask/balaclava,/obj/item/weapon/reagent_containers/spray/cleaner{pixel_x = 5},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/prison/solitary{name = "Prisoner Education Chamber"}) +"afv" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/power/apc{cell_type = 2500; dir = 1; name = "Prisoner Education Chamber APC"; pixel_y = 24},/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/obj/item/weapon/storage/backpack/duffel/security{contents = newlist(/obj/item/weapon/scalpel,/obj/item/weapon/hemostat,/obj/item/weapon/retractor,/obj/item/weapon/cautery,/obj/item/weapon/circular_saw,/obj/item/weapon/surgical_drapes,/obj/item/clothing/mask/surgical); desc = "A large duffelbag for holding extra supplies - this one has a material inlay with space for various sharp-looking tools."; name = "duffelbag"; pixel_y = 5},/obj/item/clothing/mask/balaclava,/obj/item/weapon/reagent_containers/spray/cleaner{pixel_x = 5},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/prison/solitary{name = "Prisoner Education Chamber"}) "afw" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/wall/r_wall,/area/security/prison) "afx" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "permacell3"; name = "Cell Shutters"; opacity = 0},/obj/machinery/door/airlock/glass{id_tag = "permabolt3"; name = "Cell 3"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prison) "afy" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/security/prison) @@ -1343,7 +1343,7 @@ "azQ" = (/obj/structure/disposalpipe/sortjunction{dir = 1; icon_state = "pipe-j2s"; sortType = 1},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 8},/area/maintenance/fpmaint2{name = "Port Maintenance"}) "azR" = (/obj/structure/disposalpipe/segment,/mob/living/simple_animal/mouse,/turf/simulated/floor/plating{tag = "icon-platingdmg2"; icon_state = "platingdmg2"},/area/maintenance/fpmaint2{name = "Port Maintenance"}) "azS" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/maintenance/fpmaint2{name = "Port Maintenance"}) -"azT" = (/obj/structure/grille,/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/obj/structure/shuttle/window,/turf/simulated/shuttle/plating,/area/shuttle/siberia) +"azT" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/mining{name = "Mining Office"; req_access_txt = "48"},/turf/simulated/floor/plasteel,/area/quartermaster/miningdock{name = "\improper Mining Office"}) "azU" = (/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia) "azV" = (/obj/machinery/flasher_button{id = "gulagshuttleflasher"; name = "Flash Control"; pixel_x = 0; pixel_y = -26; req_access_txt = "1"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia) "azW" = (/obj/machinery/mineral/labor_claim_console{machinedir = 2; pixel_x = 30; pixel_y = 30},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia) @@ -1679,7 +1679,7 @@ "aGo" = (/obj/machinery/light,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 6},/area/security/nuke_storage) "aGp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{icon_state = "vault"},/area/security/nuke_storage) "aGq" = (/obj/machinery/camera/motion{c_tag = "Vault"; dir = 1; network = list("MiniSat")},/obj/machinery/light,/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 10},/area/security/nuke_storage) -"aGr" = (/obj/structure/safe,/obj/item/weapon/storage/secure/briefcase{contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/weapon/gun/projectile/automatic/pistol,/obj/item/weapon/suppressor,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/weapon/soap/nanotrasen)},/obj/item/weapon/storage/backpack/duffel{contents = newlist(/obj/item/clothing/under/lawyer,/obj/item/clothing/accessory/waistcoat,/obj/item/clothing/shoes/laceup,/obj/item/clothing/gloves/color/black,/obj/item/clothing/glasses/sunglasses,/obj/item/clothing/head/fedora); desc = "A large dufflebag for holding extra things. There is a NanoTrasen logo on the back."; icon_state = "duffle-syndieammo"; item_state = "duffle-syndieammo"},/obj/item/weapon/card/id/silver{access = list(12); assignment = "Reaper"; name = "Thirteen's ID Card (Reaper)"; registered_name = "Thirteen"},/obj/item/weapon/lazarus_injector,/obj/item/weapon/gun/energy/gun/advtaser,/obj/item/weapon/gun/projectile/revolver/russian,/obj/item/ammo_box/a357,/obj/item/clothing/accessory/stethoscope,/obj/item/weapon/book{desc = "An undeniably handy book."; icon_state = "bookknock"; name = "A Simpleton's Guide to Safe-cracking with Stethoscopes"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 4},/area/security/nuke_storage) +"aGr" = (/obj/structure/safe,/obj/item/weapon/storage/secure/briefcase{contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/weapon/gun/projectile/automatic/pistol,/obj/item/weapon/suppressor,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/weapon/soap/nanotrasen)},/obj/item/weapon/storage/backpack/duffel{contents = newlist(/obj/item/clothing/under/lawyer,/obj/item/clothing/accessory/waistcoat,/obj/item/clothing/shoes/laceup,/obj/item/clothing/gloves/color/black,/obj/item/clothing/glasses/sunglasses,/obj/item/clothing/head/fedora); desc = "A large duffelbag for holding extra things. There is a NanoTrasen logo on the back."; icon_state = "duffel-syndieammo"; item_state = "duffel-syndieammo"},/obj/item/weapon/card/id/silver{access = list(12); assignment = "Reaper"; name = "Thirteen's ID Card (Reaper)"; registered_name = "Thirteen"},/obj/item/weapon/lazarus_injector,/obj/item/weapon/gun/energy/gun/advtaser,/obj/item/weapon/gun/projectile/revolver/russian,/obj/item/ammo_box/a357,/obj/item/clothing/accessory/stethoscope,/obj/item/weapon/book{desc = "An undeniably handy book."; icon_state = "bookknock"; name = "A Simpleton's Guide to Safe-cracking with Stethoscopes"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 4},/area/security/nuke_storage) "aGs" = (/obj/structure/shuttle/engine/heater,/obj/structure/window/reinforced{dir = 1; layer = 2.9},/turf/simulated/shuttle/plating,/area/shuttle/siberia) "aGt" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_security{name = "Labor Camp Shuttle Airlock"; req_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/hallway/primary/fore) "aGu" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/obj/machinery/door/poddoor/preopen{id_tag = "Secure Gate"; name = "brig shutters"},/turf/simulated/floor/plating,/area/security/brig) @@ -1959,7 +1959,7 @@ "aLI" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/supply) "aLJ" = (/turf/space,/turf/simulated/shuttle/wall{tag = "icon-swall_f10"; icon_state = "swall_f10"; dir = 2},/area/shuttle/supply) "aLK" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/effect/spawner/window{useFull = 1; tag = "fullWin"},/turf/simulated/floor/plating,/area/quartermaster/miningdock{name = "\improper Mining Office"}) -"aLL" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/mining{name = "Mining Office"; req_access_txt = "48"},/turf/simulated/floor/plasteel,/area/quartermaster/miningdock{name = "\improper Mining Office"}) +"aLL" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/centcom{name = "Courtroom"; opacity = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/crew_quarters/courtroom) "aLM" = (/obj/structure/disposalpipe/segment,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/turf/simulated/floor/plasteel{dir = 9; icon_state = "warning"},/area/quartermaster/storage) "aLN" = (/obj/machinery/door_control{id = "qm_warehouse"; name = "Warehouse Door Control"; pixel_x = 0; pixel_y = 24; req_access_txt = "50"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/quartermaster/storage) "aLO" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/quartermaster/storage) @@ -2777,7 +2777,7 @@ "bbu" = (/obj/item/device/radio/intercom{frequency = 1459; name = "Station Intercom (General)"; pixel_x = 0; pixel_y = 21},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/hallway/primary/central) "bbv" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/light{dir = 1},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/hallway/primary/central) "bbw" = (/obj/structure/extinguisher_cabinet{pixel_x = 27; pixel_y = 0},/obj/item/weapon/twohanded/required/kirbyplants{icon_state = "plant-16"; layer = 4.1; tag = "icon-plant-16"},/turf/simulated/floor/plasteel{dir = 5; icon_state = "neutral"},/area/hallway/primary/central) -"bbx" = (/obj/structure/disposalpipe/segment,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/centcom{name = "Courtroom"; opacity = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/crew_quarters/courtroom) +"bbx" = (/obj/machinery/door/airlock/highsecurity{name = "Secure Tech Storage"; req_access_txt = "19;23"},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) "bby" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass{name = "Crew Quarters Access"},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plasteel,/area/crew_quarters/locker) "bbz" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass{name = "Crew Quarters Access"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/crew_quarters/locker) "bbA" = (/obj/structure/sign/pods,/turf/simulated/wall,/area/crew_quarters/locker) @@ -3102,7 +3102,7 @@ "bhH" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/turf/simulated/floor/plating,/area/storage/tech) "bhI" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/circuitboard/crew{pixel_x = -1; pixel_y = 1},/obj/item/weapon/circuitboard/card{pixel_x = 2; pixel_y = -2},/obj/item/weapon/circuitboard/communications{pixel_x = 5; pixel_y = -5},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) "bhJ" = (/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) -"bhK" = (/obj/machinery/door/airlock/highsecurity{name = "Secure Tech Storage"; req_access_txt = "19;23"},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) +"bhK" = (/obj/structure/reagent_dispensers/spacecleanertank{pixel_y = 30},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plasteel,/area/janitor) "bhL" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) "bhM" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 4; on = 1},/obj/effect/landmark{name = "xeno_spawn"; pixel_x = -1},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) "bhN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/storage/tech) @@ -3353,7 +3353,7 @@ "bmy" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/structure/disposalpipe/junction{dir = 2; icon_state = "pipe-j1"},/turf/simulated/floor/plasteel,/area/hallway/primary/port) "bmz" = (/turf/simulated/floor/plasteel{dir = 2; icon_state = "browncorner"},/area/hallway/primary/port) "bmA" = (/obj/machinery/door/firedoor,/turf/simulated/floor/plasteel{dir = 2; icon_state = "brown"},/area/hallway/primary/port) -"bmB" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/reagent_dispensers/spacecleanertank{pixel_y = 30},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plasteel,/area/janitor) +"bmB" = (/obj/machinery/door/airlock{icon = 'icons/obj/doors/doorint.dmi'; name = "Starboard Emergency Storage"; req_access_txt = "0"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/starboard) "bmC" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/mob/living/simple_animal/lizard{name = "Wags-His-Tail"; real_name = "Wags-His-Tail"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/janitor) "bmD" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/effect/landmark/start{name = "Janitor"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/janitor) "bmE" = (/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/obj/item/weapon/reagent_containers/glass/bucket,/obj/item/weapon/mop,/obj/structure/disposalpipe/segment,/obj/machinery/firealarm{dir = 4; pixel_x = 24},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/janitor) @@ -4166,7 +4166,7 @@ "bCf" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge) "bCg" = (/obj/machinery/hologram/holopad,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/light{dir = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge) "bCh" = (/obj/machinery/camera{c_tag = "Council Chamber"; dir = 2; network = list("SS13")},/obj/machinery/light{dir = 1},/obj/machinery/ai_status_display{pixel_y = 32},/obj/machinery/atmospherics/unary/vent_pump{dir = 2; on = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge) -"bCi" = (/obj/machinery/door/airlock{icon = 'icons/obj/doors/doorint.dmi'; name = "Starboard Emergency Storage"; req_access_txt = "0"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/starboard) +"bCi" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/structure/disposalpipe/junction{dir = 8; icon_state = "pipe-j2"; tag = "icon-pipe-j1 (WEST)"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bCj" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/machinery/light_switch{pixel_x = 28; pixel_y = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge) "bCk" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/item/device/radio/intercom{dir = 0; name = "Station Intercom (General)"; pixel_x = -26; pixel_y = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge) "bCl" = (/obj/item/weapon/hand_labeler,/obj/item/stack/packageWrap,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/table/woodentable,/obj/item/device/eftpos,/turf/simulated/floor/wood,/area/crew_quarters/heads) @@ -4531,15 +4531,15 @@ "bJg" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJh" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/landmark{name = "lightsout"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJi" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJj" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJk" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJl" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/intercom{frequency = 1459; name = "Station Intercom (General)"; pixel_x = 0; pixel_y = 21},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 2; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJj" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJk" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJl" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 2; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/structure/disposalpipe/junction{dir = 8; icon_state = "pipe-j2"; tag = "icon-pipe-j1 (WEST)"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/intercom{frequency = 1459; name = "Station Intercom (General)"; pixel_x = 0; pixel_y = 21},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJo" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bJr" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bJr" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJs" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJt" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/ai_status_display{pixel_y = 32},/turf/simulated/floor/plasteel{dir = 4; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bJu" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/power/apc{cell_type = 10000; dir = 1; name = "Command Hallway APC"; pixel_x = 0; pixel_y = 25},/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plasteel{dir = 4; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) @@ -4624,7 +4624,7 @@ "bKV" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bKW" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bKX" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 2; initialize_directions = 11},/obj/machinery/newscaster{pixel_y = -29},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) -"bKY" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/light,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 2; initialize_directions = 11},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) +"bKY" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "neutral"; dir = 1},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bKZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bLa" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel,/area/bridge/meeting_room{name = "\improper Command Hallway"}) "bLb" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel,/area/bridge/meeting_room{name = "\improper Command Hallway"}) @@ -6091,7 +6091,7 @@ "cng" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Medbay Storage"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay2{name = "Medbay Storage"}) "cnh" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/medical/medbay2{name = "Medbay Storage"}) "cni" = (/obj/machinery/door/firedoor,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Medbay Storage"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay2{name = "Medbay Storage"}) -"cnj" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/door/firedoor,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Medbay Desk"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay{name = "Medbay Central"}) +"cnj" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/light,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 2; initialize_directions = 11},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralcorner"},/area/bridge/meeting_room{name = "\improper Command Hallway"}) "cnk" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/medical/medbay{name = "Medbay Central"}) "cnl" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_medical{id_tag = "MedbayFoyer"; name = "Medbay"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay{name = "Medbay Central"}) "cnm" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_medical{id_tag = "MedbayFoyer"; name = "Medbay"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay{name = "Medbay Central"}) @@ -6131,7 +6131,7 @@ "cnU" = (/obj/structure/reagent_dispensers/watertank,/obj/item/weapon/extinguisher,/obj/machinery/light/small,/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -31},/turf/simulated/floor/plating,/area/maintenance/incinerator) "cnV" = (/obj/structure/disposalpipe/segment,/obj/machinery/computer/turbine_computer{id = "incineratorturbine"},/obj/machinery/atmospherics/pipe/simple/insulated,/obj/machinery/computer/security/telescreen{desc = "Used for watching the turbine vent."; dir = 8; name = "turbine vent monitor"; network = list("Turbine"); pixel_x = 29; pixel_y = 0},/obj/machinery/door_control{id = "turbinevent"; name = "Turbine Vent Control"; pixel_x = 24; pixel_y = -24; req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/incinerator) "cnW" = (/obj/machinery/door/airlock/glass{autoclose = 0; frequency = 1449; heat_proof = 1; icon_state = "door_locked"; id_tag = "incinerator_airlock_exterior"; locked = 1; name = "Incinerator Exterior Airlock"; req_access_txt = "12"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plasteel,/area/maintenance/incinerator) -"cnX" = (/obj/machinery/atmospherics/pipe/simple/insulated,/turf/simulated/wall/r_wall,/area/maintenance/incinerator) +"cnX" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 2},/turf/simulated/wall/r_wall/coated,/area/maintenance/incinerator) "cnY" = (/obj/machinery/atmospherics/pipe/simple,/obj/machinery/meter,/obj/structure/grille,/turf/simulated/wall/r_wall,/area/atmos) "cnZ" = (/obj/machinery/atmospherics/pipe/simple,/obj/machinery/meter{frequency = 1443; id = "mair_in_meter"; name = "Mixed Air Tank In"},/obj/structure/grille,/turf/simulated/wall/r_wall,/area/atmos) "coa" = (/obj/machinery/atmospherics/pipe/simple,/obj/machinery/meter{frequency = 1443; id = "mair_out_meter"; name = "Mixed Air Tank Out"},/obj/structure/grille,/turf/simulated/wall/r_wall,/area/atmos) @@ -6188,7 +6188,7 @@ "coZ" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1; scrub_Toxins = 0},/turf/simulated/floor/engine,/area/toxins/explab) "cpa" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/engine,/area/toxins/explab) "cpb" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/turf/simulated/floor/plating{tag = "icon-platingdmg1"; icon_state = "platingdmg1"},/area/maintenance/aft{name = "Aft Maintenance"}) -"cpc" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/machinery/atmospherics/pipe/simple/insulated,/turf/simulated/floor/plating,/area/maintenance/incinerator) +"cpc" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel,/area/bridge/meeting_room{name = "\improper Command Hallway"}) "cpd" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1; frequency = 1443; id = "air_in"},/turf/simulated/floor/plating/airless,/area/maintenance/incinerator) "cpe" = (/obj/machinery/igniter{icon_state = "igniter0"; id = "Incinerator"; luminosity = 2; on = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating/airless,/area/maintenance/incinerator) "cpf" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; external_pressure_bound = 0; initialize_directions = 1; internal_pressure_bound = 4000; on = 0; pressure_checks = 2; pump_direction = 0},/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0; pixel_y = -32},/turf/simulated/floor/plating/airless,/area/maintenance/incinerator) @@ -6299,7 +6299,7 @@ "crg" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) "crh" = (/obj/structure/stool/bed/chair,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) "cri" = (/obj/structure/stool/bed/chair,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) -"crj" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical{name = "Observation"; req_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) +"crj" = (/obj/machinery/door/firedoor,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Medbay Desk"; req_access_txt = "5"},/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/medbay{name = "Medbay Central"}) "crk" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) "crl" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) "crm" = (/obj/item/weapon/cigbutt,/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/structure/sign/nosmoking_2{pixel_x = 28},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) @@ -6307,6 +6307,7 @@ "cro" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/sleeper,/turf/simulated/floor/plasteel{icon_state = "whitebluefull"},/area/medical/sleeper{name = "Sleepers"}) "crp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 2; icon_state = "whiteblue"},/area/medical/sleeper{name = "Sleepers"}) "crq" = (/obj/machinery/door_control{id = "telelab"; name = "Test Chamber Blast Doors"; pixel_x = 0; pixel_y = 25},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/obj/structure/table/reinforced,/obj/item/weapon/reagent_containers/glass/bottle/epinephrine{pixel_x = 7; pixel_y = 2},/obj/item/weapon/reagent_containers/glass/bottle/charcoal{pixel_x = -2; pixel_y = -1},/obj/item/weapon/reagent_containers/dropper,/obj/item/stack/medical/bruise_pack/advanced,/obj/item/stack/medical/ointment/advanced,/obj/item/device/healthanalyzer,/turf/simulated/floor/plasteel{dir = 2; icon_state = "warning"},/area/toxins/explab) +"crr" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/beacon,/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) "crs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/effect/spawner/window{useFull = 1; tag = "fullWin"},/turf/simulated/floor/plating,/area/medical/sleeper{name = "Sleepers"}) "crt" = (/obj/structure/sink{dir = 8; icon_state = "sink"; pixel_x = -12; pixel_y = 2},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitebluecorner"},/area/medical/medbay{name = "Medbay Central"}) "cru" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/medbay{name = "Medbay Central"}) @@ -6403,6 +6404,7 @@ "cth" = (/obj/structure/table/reinforced,/obj/item/weapon/hand_labeler,/obj/item/stack/packageWrap,/obj/item/stack/packageWrap,/obj/item/stack/packageWrap,/obj/item/device/taperecorder{pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{dir = 2; icon_state = "warning"},/area/toxins/explab) "cti" = (/obj/machinery/computer/rdconsole/experiment,/turf/simulated/floor/plasteel{dir = 2; icon_state = "warning"},/area/toxins/explab) "ctj" = (/obj/structure/table/reinforced,/obj/item/weapon/clipboard,/obj/item/weapon/book/manual/experimentor,/turf/simulated/floor/plasteel{dir = 2; icon_state = "warning"},/area/toxins/explab) +"ctk" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/machinery/atmospherics/pipe/simple/insulated,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/incinerator) "ctl" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plasteel{dir = 2; icon_state = "warning"},/area/toxins/explab) "ctm" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = 1},/obj/effect/spawner/lootdrop{loot = list(/obj/structure/grille,/obj/structure/grille,/obj/structure/grille,/obj/structure/grille,/obj/structure/grille,/obj/item/weapon/cigbutt,/obj/item/trash/cheesie,/obj/item/trash/candy,/obj/item/trash/chips,/obj/item/trash/pistachios,/obj/item/trash/plate,/obj/item/trash/popcorn,/obj/item/trash/raisins,/obj/item/trash/sosjerky,/obj/item/trash/syndi_cakes); name = "maint grille or trash spawner"},/turf/simulated/floor/plating,/area/maintenance/aft{name = "Aft Maintenance"}) "ctn" = (/obj/structure/closet/crate{icon_state = "crateopen"; opened = 1},/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/maintenance/aft{name = "Aft Maintenance"}) @@ -6412,7 +6414,7 @@ "ctr" = (/obj/machinery/chem_heater,/turf/simulated/floor/plating,/area/maintenance/aft{name = "Aft Maintenance"}) "cts" = (/obj/structure/lattice,/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/space,/area/space) "ctt" = (/obj/structure/disposaloutlet{dir = 2},/obj/structure/disposalpipe/trunk{dir = 8},/turf/simulated/floor/plating/airless,/area/space) -"ctu" = (/obj/structure/sign/fire{pixel_x = 0; pixel_y = 0},/turf/simulated/wall/r_wall,/area/maintenance/incinerator) +"ctu" = (/turf/simulated/wall/r_wall/coated,/area/maintenance/incinerator) "ctv" = (/obj/machinery/door/poddoor{id_tag = "turbinevent"; name = "Turbine Vent"},/turf/simulated/floor/plating/airless,/area/maintenance/incinerator) "ctw" = (/obj/item/device/flashlight/lamp,/obj/structure/table/woodentable,/turf/simulated/floor/wood,/area/maintenance/aft{name = "Aft Maintenance"}) "ctx" = (/obj/item/weapon/reagent_containers/food/drinks/cans/beer,/obj/structure/table/woodentable,/turf/simulated/floor/wood,/area/maintenance/aft{name = "Aft Maintenance"}) @@ -6896,7 +6898,7 @@ "cCH" = (/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 2; on = 1; scrub_Toxins = 0},/obj/structure/sign/nosmoking_2{pixel_x = -28; pixel_y = 0},/turf/simulated/floor/plasteel,/area/assembly/chargebay) "cCI" = (/obj/machinery/mech_bay_recharge_port,/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/assembly/chargebay) "cCJ" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 31},/turf/simulated/floor/mech_bay_recharge_floor,/area/assembly/chargebay) -"cCK" = (/obj/machinery/computer/mech_bay_power_console,/obj/item/device/radio/intercom{broadcasting = 0; listening = 1; name = "Station Intercom (General)"; pixel_y = 20},/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/bluegrid{icon_state = "gcircuit"},/area/assembly/chargebay) +"cCK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical{name = "Observation"; req_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/surgery) "cCL" = (/turf/simulated/floor/plasteel{dir = 10; icon_state = "warning"},/area/toxins/misc_lab{name = "\improper Research Testing Range"}) "cCM" = (/turf/simulated/floor/plasteel{dir = 6; icon_state = "warning"},/area/toxins/misc_lab{name = "\improper Research Testing Range"}) "cCN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera{c_tag = "Research Division Hallway - Mech Bay"; dir = 4; network = list("SS13","RD")},/obj/machinery/alarm{dir = 4; pixel_x = -23; pixel_y = 0},/turf/simulated/floor/plasteel{dir = 6; icon_state = "whitehall"},/area/medical/research{name = "Research Division"}) @@ -7030,7 +7032,7 @@ "cFl" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11},/obj/machinery/door_control{dir = 2; id = "Skynet_launch"; name = "Mech Bay Door Control"; pixel_x = 26; pixel_y = 6; req_one_access_txt = "29"},/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralcorner"},/area/hallway/primary/aft) "cFm" = (/obj/machinery/door_control{dir = 2; id = "Skynet_launch"; name = "Mech Bay Door Control"; pixel_x = -26; pixel_y = 6},/obj/machinery/light_switch{pixel_x = -23; pixel_y = -2},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel,/area/assembly/chargebay) "cFn" = (/turf/simulated/floor/mech_bay_recharge_floor,/area/assembly/chargebay) -"cFo" = (/obj/machinery/computer/mech_bay_power_console,/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/bluegrid,/area/assembly/chargebay) +"cFo" = (/obj/machinery/computer/mech_bay_power_console,/obj/item/device/radio/intercom{broadcasting = 0; listening = 1; name = "Station Intercom (General)"; pixel_y = 20},/turf/simulated/floor/bluegrid{icon_state = "gcircuit"},/area/assembly/chargebay) "cFp" = (/obj/structure/table/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/extinguisher_cabinet{pixel_x = -27; pixel_y = 0},/obj/item/weapon/folder/white,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 8; icon_state = "warning"},/area/toxins/misc_lab{name = "\improper Research Testing Range"}) "cFq" = (/obj/machinery/door/window/westleft{base_state = "right"; dir = 1; icon_state = "right"; name = "door"; req_access_txt = "0"},/turf/simulated/floor/plasteel,/area/toxins/misc_lab{name = "\improper Research Testing Range"}) "cFr" = (/obj/structure/table/reinforced,/obj/machinery/magnetic_controller{autolink = 1; pixel_y = 3},/obj/structure/window/reinforced{dir = 1},/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/item/clothing/ears/earmuffs,/turf/simulated/floor/plasteel{dir = 4; icon_state = "warning"},/area/toxins/misc_lab{name = "\improper Research Testing Range"}) @@ -7444,7 +7446,7 @@ "cNj" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "whitepurplecorner"},/area/medical/research{name = "Research Division"}) "cNk" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) "cNl" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11},/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitebluecorner"},/area/medical/research{name = "Research Division"}) -"cNm" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/sign/securearea{desc = "A warning sign which reads 'SERVER ROOM'."; name = "SERVER ROOM"; pixel_y = 0},/turf/simulated/wall/r_wall,/area/toxins/server{name = "\improper Research Division Server Room"}) +"cNm" = (/obj/machinery/atmospherics/pipe/simple/insulated,/turf/simulated/wall/r_wall/coated,/area/maintenance/incinerator) "cNn" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/toxins/server{name = "\improper Research Division Server Room"}) "cNo" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 2; initialize_directions = 11},/turf/simulated/wall/r_wall,/area/toxins/server{name = "\improper Research Division Server Room"}) "cNp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/toxins/mixing{name = "\improper Toxins Lab"}) @@ -7902,7 +7904,7 @@ "cVZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) "cWa" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel,/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) "cWb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{tag = "icon-warningcorner (WEST)"; icon_state = "warningcorner"; dir = 8},/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) -"cWc" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/beacon,/obj/machinery/embedded_controller/radio/airlock/docking_port_multi{id_tag = "escape_dock_north_airlock"; master_tag = "escape_dock"; pixel_y = 30; req_one_access_txt = "13"; tag_airpump = "escape_dock_north_pump"; tag_chamber_sensor = "escape_dock_north_sensor"; tag_exterior_door = "escape_dock_north_outer"; tag_interior_door = "escape_dock_north_inner"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) +"cWc" = (/obj/machinery/computer/mech_bay_power_console,/turf/simulated/floor/bluegrid,/area/assembly/chargebay) "cWd" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{tag = "icon-warningcorner (EAST)"; icon_state = "warningcorner"; dir = 4},/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) "cWe" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/obj/machinery/navbeacon{codes_txt = "patrol;next_patrol=9.5-Escape2"; location = "9-Escape"},/mob/living/simple_animal/bot/secbot{auto_patrol = 1; health = 35; maxHealth = 35; name = "Inspector Johnson"},/turf/simulated/floor/plasteel,/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) "cWf" = (/obj/machinery/camera{c_tag = "Departure Lounge - Starboard Aft"; dir = 8; network = list("SS13")},/obj/machinery/light{dir = 4},/obj/item/device/radio/intercom{frequency = 1459; name = "Station Intercom (General)"; pixel_x = 29},/obj/item/weapon/twohanded/required/kirbyplants{icon_state = "plant-16"; layer = 4.1; tag = "icon-plant-16"},/turf/simulated/floor/plasteel{dir = 4; icon_state = "warning"},/area/hallway/secondary/exit{name = "\improper Departure Lounge"}) @@ -8169,6 +8171,7 @@ "dbg" = (/obj/effect/landmark{name = "xeno_spawn"; pixel_x = -1},/turf/simulated/floor/plating/airless/catwalk,/area/solar/starboard) "dbh" = (/obj/machinery/status_display,/turf/simulated/shuttle/wall{tag = "icon-swall3"; icon_state = "swall3"; dir = 2},/area/shuttle/escape) "dbi" = (/obj/machinery/sleeper,/turf/simulated/shuttle/floor,/area/shuttle/escape) +"dbj" = (/obj/structure/sign/fire{pixel_x = 0; pixel_y = 0},/turf/simulated/wall/r_wall/coated,/area/maintenance/incinerator) "dbk" = (/obj/machinery/optable,/turf/simulated/shuttle/floor,/area/shuttle/escape) "dbl" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/structure/cable/yellow,/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/obj/machinery/door/poddoor/preopen{id_tag = "xenobio2"; name = "containment blast door"},/turf/simulated/floor/plating,/area/toxins/xenobiology{name = "\improper Secure Lab"}) "dbm" = (/obj/structure/table/reinforced,/obj/machinery/door_control{id = "xenobio2"; name = "Containment Blast Doors"; pixel_x = 0; pixel_y = 4; req_access_txt = "55"},/obj/structure/window/reinforced{dir = 1},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel{dir = 5; icon_state = "warning"},/area/toxins/xenobiology{name = "\improper Secure Lab"}) @@ -8463,6 +8466,10 @@ "dgP" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/wall/r_wall,/area/engine/break_room) "dgQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/transit_tube{tag = "icon-E-W-Pass"; icon_state = "E-W-Pass"},/turf/simulated/floor/plating/airless,/area/space) "dgR" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/hallway/secondary/entry{name = "Arrivals"}) +"dgS" = (/turf/simulated/wall/r_wall/coated,/area/toxins/mixing{name = "\improper Toxins Lab"}) +"dgT" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/wall/r_wall/coated,/area/toxins/mixing{name = "\improper Toxins Lab"}) +"dgU" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall/coated,/area/toxins/server{name = "\improper Research Division Server Room"}) +"dgV" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/sign/securearea{desc = "A warning sign which reads 'SERVER ROOM'."; name = "SERVER ROOM"; pixel_y = 0},/turf/simulated/wall/r_wall/coated,/area/toxins/server{name = "\improper Research Division Server Room"}) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8554,16 +8561,16 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarAabqarAabqarAarAarAataabqabqabqarAarAabqaaaabqabqakzavQavRavSavTavUavUavUavUavUavVavWavXavYavZawaawbavUawcavUawdaweawfajgajgajgajgajgajgajgajgajgajgawgajgawhajgajgajgajgajgajgamxawiawjaqJatqatratsawkawlawmawnawoawpawqawraqTawsawtawuasgawvdfvdfwawyawzawAawBawCawDawEawFatKawGawHawGawIamOawJawKawLawMavqavrawNawOawPawQawRawSawTavvawUawVawWavvaoGaoGasJaubavBasIaoGayvaoGavzasJawXasJaoGawYayqamkamkaxaaxbamkayxasTasTaxdaxeaxhaxhbnIaxhbnJbplaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarAarAarAarAarAabqarAarAabqauparAarAabqabqabqabqapfapfaxiapfapfaxjaxkaxkaxkaxkaxkaxlapfapfapfapfaxmaxnaxoaxoaxoaxoaxpaxqajgaxraxsaxtaxuaxvaxwaxxaxyaxzaxAaxBaxCajgaxDaxEaxEaxEaxFamzaxGaxHaqJaxIaxJaxKaqTaxLagBagBaxMaxNaxOasgagBaxPaxMakHakHamOaxQaxRaxSaxQamOaxTaxUamOaxVatKatKaxWaxWaxWamOamOaxXafbdeeaxZdefavrayaaybayaawQaycaydayeayfaygayhayiavvayjaoGaykaylaymaynaoGasMaoGaoGaoGayoaoGaoGaypbppayramkamkamkamkazrasIazGazFbTiaxhdfCdgCdfEaxhaxhaxhabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqarAarAarAarAarAarAarAarAarAarAarAayyarAabqaupapfapfapfayzayAapfabqabqabqabqabqabqabqabqabqabqabqapfaqBayBapdaoXayCaoXayDayEayFayGayHayIajgajgajgayJayKayKayKayLajgajgayMayNayOayPayMamzamzakDayQayRapnaySaySayTayUaySayVaySayUaySayWaySayVayXayYayZayUazaazbaySaySaySayUaySaOPamxazdazeazeazeazeakDatLafbaxYavoavqavrazfazgazhavraziazjazkazlazmavvavvavvaznaoGasIazoawXasJaoGayvaoGazpaoGazqdfFazsbpmdfobpobqVbpqbqXbqWbqWbqWbqWdeSdgCdeVdgCdgCdgCaxgazHaxgaefaefaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaupabqarAataarAarAarAarAazIabqarAarAarAarAarAarAazJazKazJazLazMapfapfabqaaaaaaaaaaaaaaaaaaaaaaaaabqapfapfapfathaoXapdaoXazNazOazPazQazRazSajgaaaabqaaaaaaaaaaaaaaaabqaaaazTazUazVazWazXazYazeazZaAaaAbaAcaAdaAdaAeaAcaAdaAfaAgaAcaAhaAiaAdaAjaAkaAlaAdaAmaAnaAoaApaApaAqaAraAsaAtaAuaAvaAwaAxaAyaAzakDatLafbaxYaAAavqavraABaACaADaAEaAFaAGaAHavvaAIaAJaAKavvaALaoGaoGaoGayoaoGaoGasJaoGaucaoGaAMaxhaxhawYaANamkaxhaxhaxhaxhaxhaxhaxhaxhaxhayxaxhaxhaxhaxhaxhaAOaxhabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaupabqarAataarAarAarAarAazIabqarAarAarAarAarAarAazJazKazJazLazMapfapfabqaaaaaaaaaaaaaaaaaaaaaaaaabqapfapfapfathaoXapdaoXazNazOazPazQazRazSajgaaaabqaaaaaaaaaaaaaaaabqaaaaxEazUazVazWazXazYazeazZaAaaAbaAcaAdaAdaAeaAcaAdaAfaAgaAcaAhaAiaAdaAjaAkaAlaAdaAmaAnaAoaApaApaAqaAraAsaAtaAuaAvaAwaAxaAyaAzakDatLafbaxYaAAavqavraABaACaADaAEaAFaAGaAHavvaAIaAJaAKavvaALaoGaoGaoGayoaoGaoGasJaoGaucaoGaAMaxhaxhawYaANamkaxhaxhaxhaxhaxhaxhaxhaxhaxhayxaxhaxhaxhaxhaxhaAOaxhabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarAarAarAarAarAarAarAarAarAarAarAabqarAarAarAabqapfapfapfaAPazSapdapfaaaaAQaARaASaARaATabqabqabqabqapfaAUapfaAVavUavUavUaAWaAXapfaAYaAZaBaajgaaaaBbaBbaBbaBbaBbaBbaBbaaaayMaBcaBdaBeayMamzamzakDaBfaBgaBhaBiaBjaBkaBhaBlaBjaBgaBmaBnaBoaBpaBqaBraBsaBtaBuaBvaBwaBxaByaBwaBzaBAaBBaBCaBDaBEaBFaBGaBHakDatLaBIaBIaBIaBIavraBJaPWaBLaBMaBNaBOayeaBPaBQaBRaBSavvaBTaBUaBVaBWaBXaBWaBYaBWaBZaBWdgEaCaaCbaCcaCdaCeaCfaCgaChaCgaCiaCjaCkaCjaClaxhaxhaxhaCiaCjaClaCmaCmaCgabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqarAarAarAarAarAarAarAaCnarAabqabqabqabqapfaoXazSarIakzaaaaCoaCpaCqaCpaCoaCraCraCraCsaCsaCsaCsaCtaCsaCsaCuaCuaCuaCuaCvaCuaCwajgabqaBbaCxaCyaCzaCAaCBaBbaaaayMaCCaCCaCDayMaaaaaaaCEaCFaCGaCHakDaCFaCIaCHakDaCFaCJaCHakDaCKamzaCLakDamzaCMaCNamzamzaCOaCOaCPaCQaCRaCOaCOaCSakDakDakDakDakDatLaBIaQdaCUaQvavravravravravraCWaCXaCYazlazmavvavvavvaoGaCZasIarrasJasIaDadgIaxhaxhaxhaxhaxhaDbaDcaDdaDeaDfdfMaDfaDhaDiaDjaDiaDkaCjaDlaCjaDmaDiaDjaDiaCmaDnaDoabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqabqabqarAarAarAarAataarAarAarAaDparAarAarAarAabqaaaabqakzayBazSaqwapfaaaaASaDqaDraDqaASaCraDsaDtaCsaDuaDvaDwaDxaDyaCsaDzaDAaDBaDCaDDaCuaCwajgaaaaBbaDEaDFaDGaDHaDIaBbaaaazTaDJaCCaDKayMaDLaDLacAaDMaDNaDOakDaDPaDNaDOakDaDQaDNaDOakDaDRaDSaDTakDaDUaDVaDWaDXaDYaCOaDZaEaaEbaEcaEdaEeaCSaEfaEgaEgaEhaEgaEiaBIaRtaEkaRyaBIaEmaEnaEmavvaEoaEpaEqaEraEsaEtaEuaEvaBWaEwaxhaxhaxhaxhaxhaxhaxhaExaExaEyaEzaEAaEBaECaEDaCgaCgaCgabqabqaEEaEFaDiaDiaDiaDiaDiaEGaEEaDiaEHaCgaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqabqabqarAarAarAarAataarAarAarAaDparAarAarAarAabqaaaabqakzayBazSaqwapfaaaaASaDqaDraDqaASaCraDsaDtaCsaDuaDvaDwaDxaDyaCsaDzaDAaDBaDCaDDaCuaCwajgaaaaBbaDEaDFaDGaDHaDIaBbaaaaxEaDJaCCaDKayMaDLaDLacAaDMaDNaDOakDaDPaDNaDOakDaDQaDNaDOakDaDRaDSaDTakDaDUaDVaDWaDXaDYaCOaDZaEaaEbaEcaEdaEeaCSaEfaEgaEgaEhaEgaEiaBIaRtaEkaRyaBIaEmaEnaEmavvaEoaEpaEqaEraEsaEtaEuaEvaBWaEwaxhaxhaxhaxhaxhaxhaxhaExaExaEyaEzaEAaEBaECaEDaCgaCgaCgabqabqaEEaEFaDiaDiaDiaDiaDiaEGaEEaDiaEHaCgaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqarAarAarAarAarAarAarAabqarAabqabqarAarAabqabqapfapfauyazSapfapfaaaaCoaDqaDqaDqaEIaEJaEKaEKaELaEMaENaEOaEPaEQaERaESaETaEUaEVaEWaCuaCwajgaaaaBbaEXaEYaEZaFaaFbaBbaaaayMaFcaCCaCCaFdaFeaFfacAaFgaDNaFhakDaFgaDNaFiakDaFgaDNaFjakDaFkaFlaFmakDaFnaFoaFpaFqaFraCOaFsaFtaFuaFvaFwaFxaCSaFyaFzaFzaFzaFAaFBaBIaTeaFDaThaBIaFFaFGaFGaFHaFIaFJaFKavvavvavvavvavvaoGaFLaxhaFMaFNaFOaFPaFQaFRaFSaFTaFTaFTaFTaFUaFVaFWaFXaFYaCgaFZabqabqaaaaaaaaaabqabqaaaaaaabqaaaarAaDiaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaarAarAarAarAarAabqabqabqarAarAarAabeaaaabqabqabqapfaGaaoXaoXaGbakzaaaaaaaASaDraDraDraASaCraGcaGdaGeaEMaEKaGfaGgaGhaCsaGiaGjaGkaGlaGmaCuaCwajgabqaBbaGnaGoaGpaGqaGraBbaaaayMaGsaGsaGsayMaDLaGtacAaGuaGvaGwamxaGuaGvaGwamxaGuaGvaGwamxaGxaGyaGzamxamxaCMaGAamxaGBaCOaGCaGDaGEaGFaGGaGHaCSaGIajgajgajgaGJajgaBIaGKaGLaBIaBIaGMaGNaGOaGPaGQaGRaGSazlaGTaGUawWavvaGVaGWaxhaGXaGYaGZaGZaHaaHbaDcaHcaHdaHeaHeaHeaHfaHgaHhaHiaHjaMIaMKaMJaOhaMJaMJaOhaMJaMJaOhaMJaMJaPwarAaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqabqabqabqabqabqabqabqabqabqaHkaHlaHkabfaaaabqaaaabqapfaHmaHnanEazSapfapfaaaaCoaHoaHpaHqaCoaCraCraCraCsaHraEKaHsaGgaHtaCsaHuaHvaHwaHxaHyaCuaCwajgaaaaBbaHzaHAaHBaHCaBbaBbaaaaHDaHEaHEaHEaHFaHGaHHaHGaHIaHJaHIaHKaHIaHJaHIaHLaHIaHJaHMaHNaHOaHPaHQaHRaHSaHTaHUamxazeaCSaHVaHWaHXaHYaHZaIaaCSaIbaBIaIcaIdaIeaIfaIfaIgaIhaIiaIjaIkaIlaImaInaIoaIpayeaIqaIraIsaItavvaucaGWaxhaIuaIvaIwaIxaIyaIzaIAaIBaICaIDaIDaIDaIEaIFaHhaHiaHjarAaPxarAaPyarAarAaPyarAarAaPyarAarAaPxarAaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabqaaaaaaabqabqaaaaHkaIGaHkabqabqabqabqabqapfaIHapdapdaIIaIJapfaaaaIKaARaILaARaIMabqabqabqaCraINaIOaIPaIQaIRaCsaISaITaIUaIVaIWaCuaCwajgaaaabqaaaaIXaIYaIZaaaabqaaaaHGaDLaDLaDLaHGaHGaJaaJbaJcaJdaJeaJfaJgaJhaJhaJiaJhaJjaJgaJkaJlaJmaJnaJoaJpaJqaJramxazeaCSaCSaJsaJtaCSaJuaCSaCSaGIaBIaBIaBIaJvaJwaJxaJyaJzaJAaJBaJCaJDaJEaJFaJFaJGaJHavvavvavvavvavvaubaGWaxhaJIaJJaJKaJLaJMaJNaJOaJPaJQaJRaJSaJTaJUaJVaHhaHiaHjaHjaPxaJWaaaaaaaaaaaaaJWaaaaaaaJWarAaPxabqaCgaJXabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabqaaaaaaaaaabqaaaaHkaHlaHkaHkaJYaJYaJYaHkaHkaHkaHkaHkaJZaKaapfaaaaaaaaaaaaaaaaaaaaaaaaabqaCraKbaKcaKdaKeaKfaCsaKgaKhaCuaCuaCuaCuaKiajgaKjaKkaKlaKmaKnaKoaKpaKqaKjaHGaKraKsaKsaKtaKuaKvaKwaKxaKyaKzaKAaKBaTiaKDaKEaKCaKFaKGaKHaKIaKJaKKaKLaKMaKNaKOamxazeaKPaCSaKQaKRaCSaKSaKTaKUaKVaBIaKWaKXaKYaKZaBIaLaaLbaLcaBIaLdaLeaLfaLgaLfaLhaLiaLjaLkaLlaLmavvasJaGWaxhaLnaLoaLpaLqaLraFRaLsaLtaJQaLuaCgaCgaLvaLwaCgaHjaHjaHjaPxaaaaaaaaaaaaaaaaLxaaaaaaaaaaTMaRgabqaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaabqaHkaHkaLyaLzaLAaLBaLBaLCaLDaLEaLFaLGaHkaHkazSapfaaaaLHaLIaLIaLIaLIaLIaLJabqaCsaCsaCsaLKaLLaCsaCsaLMaLNaLOaLPaLQaLRaLSaLTaLUaLVaLWaLXaLYaLWaLZaMaaMbaHGaMcaMdaMeaMfaMfaMgaMfaMfaMfaMfaMfaMfaMfaMfaMgaMfaMhaMiaMjaMkaMkaMkaMlaMlaMlaMlaMlaMkaMmaMkaMnaMnaMnaMnaMoaMnaGIaBIaBIaBIaMpaMqaBIaMraBIaMsaBIaMtaMuaMvazlaMwaMxaMyazlaMzaMAaMBavvaMCaMDaxhaCgaCgaCgaCgaCgaFRaMEaMFaJQaMGaCgaMHaXGaWubssaWuddkaHjaPxaaaaaaabqabqabqabqabqaaaaaaarAaPxarAaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaabqaHkaHkaLyaLzaLAaLBaLBaLCaLDaLEaLFaLGaHkaHkazSapfaaaaLHaLIaLIaLIaLIaLIaLJabqaCsaCsaCsaLKazTaCsaCsaLMaLNaLOaLPaLQaLRaLSaLTaLUaLVaLWaLXaLYaLWaLZaMaaMbaHGaMcaMdaMeaMfaMfaMgaMfaMfaMfaMfaMfaMfaMfaMfaMgaMfaMhaMiaMjaMkaMkaMkaMlaMlaMlaMlaMlaMkaMmaMkaMnaMnaMnaMnaMoaMnaGIaBIaBIaBIaMpaMqaBIaMraBIaMsaBIaMtaMuaMvazlaMwaMxaMyazlaMzaMAaMBavvaMCaMDaxhaCgaCgaCgaCgaCgaFRaMEaMFaJQaMGaCgaMHaXGaWubssaWuddkaHjaPxaaaaaaabqabqabqabqabqaaaaaaarAaPxarAaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaHkaMLaMLaMLaLBaLBaLBaLBaLBaLBaMLaMLaMMaHkazSakzaaaaMNaMOaMOaMOaMOaMOaMNabqabqaMPaMQaMRaMSaMTaMUaMVaMWaMXaMYaMZaNaaNbaNcaLRaNdaNeaNfaNgaNhaNiaNjaNkaNlaNmaNnaNoaNpaaaaaaaaaabqaaaaaaaaaabqaaaaaaaaaaNqaNraNsaNtaMkaNuaNvaNwaNxaNyaNzaNAaNBaNCaMkaNDaUfaNFaNGaNHaMnaNIaBIaNJaNKaJwaMqaBIaNLaBIaNMaBIaNNaNOaNPaNQaNQaNQaNQaNQaNQaNQaNQaNQaoGaNRaxhaNSaNTaNUaNVaCgaNWaIvaMFaNXaNYaNZaOaaObaOcaOdaOeddRaHjaPxaJWabqabqaOgddSaOiabqaOjaaaarAaPxataaCgaDoabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaHkaOkaLBaLBaLBaLBaLBaLBaLBaLBaMLaMLaMLaOlaOmapfaaaaMNaOnaMOaMOaMOaMOaMNaOoaMPaMPaOpaOqaOraOraOsaOtaOuaOvaOwaOxapfaOyapfapfapfapfaOzaOAaOBaOCaODaOEaOAaOAaOAaOAaOFaaaaaaaOGaOGaOGaOGaOGaOGaOGaaaaaaaMfaOHaOIaOJaOKaOLaNAaOMaONaOOaVsaOQaORaOSaMkaOTaOUaOVaOWaOXaMnaOYaBIaBIaBIaOZaOZaBIaBIaBIaBIaBIaPaaPbaPcaNQaPdaPeaPfaPgaPhaPiaPjaNQaPkaGWaxhaNTaNTaPlaOdaPmaGYaPnaPoaPpaPqaCgaPraPsaPtaPuaPvddUddTddVaaaaaaabqddWcspaPzabqaaaaaaaTMaRgarAaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaabqaHkaPAaLBaLBaLBaLBaPBaLBaPCaLBaLBaMLaPDaHkaGbapfaaaaMNaMOaMOaMOaMOaMOaPEaPFaPGaPFaPHaPIaPJaPKaPLaPMaPNaPOaPPaPQaPRaPSaPTaPTaPUaPTaPVaOAaYOaPXaPYaPZaQaaQbaQcbeBaQeaQfaQgaQgaQhaQiaQjaQkaQlaQmaQmaQnaQoaQpaKGaNtaMkaQqaNAaQraNAaQsaNAaQtaNAaNAaMkaQubeLaOVaQwaQxaMnaQyaQzaQAaQBaQCaQDaQEaQFaQGaQHaQIaQJaQKaQLaNQaQMaQNaQNaQNaQOaQPaQQaNQaQRaGWaxhaQSaQSaQTaOdaPmaJJaQUaQVaQWaQXaQYaQZaRaaRbaRcaRdaOfaHjaPxaaaaReabqaRfddXaRhabqabqaJWarAaPxabqaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8574,17 +8581,17 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqaWDaWEaWFaWGaWDaHkaLCaMLaWHaWIaWJaLBaLBaLBaLBaUYaWKaHkazSapdakzaaaaMNaOnaMOaMOaMOaMOaMNaOoaMPaMPaWLaPIaRoaRoaRpaRoaOuaVjaWMaWNaVlaWOaWPaWQaWRapfazMaOAaWSaWTaWTaWUaWVaRuaUgaWWaOFabqaOGaOGaOGaWXaWYaWZaOGaOGaOGabqaMfaOHaXaaMjaXbaXcaVEaVEaVEaXdaVEaVEaXeaNCaXbaQCaXfaXgaXhaToaXiaToaTnaTpaToaXjaToaXkaTpaTqaToaTqaTpaXlaXmaNQaXnaXoaXpaXqaXraPiaQQaNQaXsaGWaxhaXtaXuaXvaXwaXxaXyaXzaXAaXBaXCaXDaXDaXEaXFaHhaHiaHjaMIdeaaMJdebaMJaMJdebaMJaMJdebaMJaMJdecabqaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaXHaXIaXJaXKaXKaXLaXKaXKaXKaXKaXMaXKaXKaXKaXKaXLaXKaXKaXNaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaWDaXPaXQaXRaXSaHkaXTaMLaXUaXVaXWaMLaMLaMLaXXaXYaXZaHkaYaaYbapfabqaYcaYdaMOaMOaMOaYeaYfabqabqaMPaWLaYgaPJaPKaYhaYiaYjaYkaYlaYmaYnaYnaYnaYnaYnapfaYoaYpaYqaYraYraYsaYtaYuaYvaYwaYxaaaaaaaaaaOGaOGaYyaOGaOGaaaaaaaaaaNqaNraYzaMjaYAaYBaYCaYDaYEaNCaNCaYFaYGaNCaYAaQCaYHaYIaYJaYKaYLaYKaYMaYNbmLaYPaYKaYKaYKaYKaYKaYKaYQaYRaYSaNQaNQaNQaNQaYTaNQaNQaNQaNQaoGaGWaxhaYVaYUaYUaUNaYWaYXaYYaYZaZaaZbaZcaZdaZeaZfaFXaZgaCgaaaabqabqaaaaaaaaaaaaabqaaaaaaabqabqarAaDiaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaXHaXIaXOaaaaaaaXLaaaaaaaaaaaaaXMaaaaaaaaaaaaaXLaaaaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaWDaWDaZiaZjaWDaWDaWDaZkaWDaWDaZlaZmaWDaWDaWDaZnaWDaWDaZoapfapfabqaZpaZqaZraZraZraZqaZsabqabqaZtaZuaPIaRoaRoaRpaRoaOuaZvaOuaZwaYnaZxaZyaZzaZAapfazSaOAaZBaZCaZDaZEaZFaZGaZHaZIaOFaZJaZKaZJaZLaZMaZNaZOaZLaZJaZKaZJaMfaZPaZQaZRaZSaMkaMkaMkaMkaZTaZUaZVaNCaZWaMkaQCaZXaTraZYaZZaZZaZZaZZaoGaoGaoGbaababbacbadbaebafaZZbagbagaoGbahazAazybaiazybajazybakazybalaxhbambambambambanbaobapbaqbarbasbataIvbaubavaCgaCgaCgabqabqbawbaxaDiaDiaDiaDiaDiaDibawaDibayaCgaCgaDoabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaXHaXIaXOaaaaaaaXLaXLaXLaXLaXLaXMaXLaXLaXLaXLaXLaaaaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaabazbaAbaBbaCbaDbaEbaBbaFbaGbaHbaGbaIbaJbaGbaKbaLbaMbaNbaOapfaaaaaabaPbaQbaQbaQbaRaaaabqaZtbaSaWLaPIaRoaRobaTbaUaOubaVbaWbaXbaYbaZbbabbbbbcapfazSaOAaOAaOAaOBaOBbbdaOFbbebbfaOFbbgbbhbbiaZLbbjbbkbblaZLbbmbbnbbobbpbbqbbrbbsbbtbbubbvbbwaMkaMkaYAbbxaYAaMkaMkaXibbybbzaXibbAbbBbbCbbDbbEbbFaoGaoGaoGaoGbbGaoGaoGaoGaoGaoGaoGaGWasIasJbbHbbHbbHbbHbbHbbHbbHbambbIbbJbbKbambbLbbMbambbNbbOaFRaFRbbPbbQbbRaDfbbSaDfbbTaDibbUaDiaCiaCjbbVaCjaClaDibbUaDiaCmaDnaDoabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfabfabeabqabqabqabqabqarBaWvbbWbbXbbXbbXbbXbbXbbYbbYbbYbbZbbYbbYbbYbbXbcabbXbbXbbXbcbaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaabazbaAbaBbaCbaDbaEbaBbaFbaGbaHbaGbaIbaJbaGbaKbaLbaMbaNbaOapfaaaaaabaPbaQbaQbaQbaRaaaabqaZtbaSaWLaPIaRoaRobaTbaUaOubaVbaWbaXbaYbaZbbabbbbbcapfazSaOAaOAaOAaOBaOBbbdaOFbbebbfaOFbbgbbhbbiaZLbbjbbkbblaZLbbmbbnbbobbpbbqbbrbbsbbtbbubbvbbwaMkaMkaYAaLLaYAaMkaMkaXibbybbzaXibbAbbBbbCbbDbbEbbFaoGaoGaoGaoGbbGaoGaoGaoGaoGaoGaoGaGWasIasJbbHbbHbbHbbHbbHbbHbbHbambbIbbJbbKbambbLbbMbambbNbbOaFRaFRbbPbbQbbRaDfbbSaDfbbTaDibbUaDiaCiaCjbbVaCjaClaDibbUaDiaCmaDnaDoabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfabfabeabqabqabqabqabqarBaWvbbWbbXbbXbbXbbXbbXbbYbbYbbYbbZbbYbbYbbYbbXbcabbXbbXbbXbcbaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaabccbcdbcebcebcfbcebcebcebcgbchbcibcjbckbckbckbclbcmbcnbcoapfaaaaaaabqabqaaaaaaabqabqabqaZtbcpbcqbcrbcsaRobctbcubcvbcwbcxbcybczbcAbcBbcCbcDapfbcEbcFbcGbcHbcIbcJbcKbcLbcMbcNbcObcPbcQbcPbcRbcSbcTbcUbcVbcPbcWbcXbcXbcYbcZbdabcXbcXbdbbdcbdcbdcbddbdebdcbdcbdfbdcbdgbdhbdcbdcbdcbdibdjaoGbdkbdlbdmbdnbdobdpbdobdqbdobdrazBbakbalaubasJbbHbdsbdtbdubdvbdwbdxbambdybdzbdzbdAbdzbdBbambdCbarbdDbdEbdEbdEbdEbdEbdFaCgbdGaCjbdHaCjaDmaCgaCgaCgbdGaCjaDmaCmaCmaCgabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaarBaXHaXIaXOaaaaXLbdIbdIbdJbdKbdLbdMbdNbdKbdObdIbdPaXLaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqbccbccbdQbccaWDbccbdRbccbcdbcebdSbdTbccbdRbccbdUbdVbdWbdXapfapfapfapfakzakzakzapfapfapfaZtbdYbdZbdZbdZbdZbeaaRobebbecbedbeeaYnaYnaYnaYnbefapfapfbegapfapfbehbeibejbekbelbembenbekbelbeobepbembeqbekbekbekbelbekbekberbesbekbekbekbekbekbekbekbetbeubekbekbenbevbewbekbekbekbekbexbeybezbezbezbeAbezbezbezaoGbmMaoGaGWaoGaoGbeCbeCbeCbeCbeDbeEbeEbeFbeGbeHbambeIbeJbeKbmNbeMbeNbambeObePbeQbdEbeRbeSbeTbdEbeUaCgaCgaCgaCgaCgaCgaCgbeVaCgaCgaCgaCgaCgaLwaCgabqarBarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabearBarBarBarBarBarBarBarBaWvaXIaXOaaaaXLbdIbdLbeWbeXbeYbeZbfabeXbfbbdLbdPaXLaaaaZhaXIaXObfcbfcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaabccabqaaaabqaaabccbfdbccbfebfebffbfgbccbfdbccbccaWDbfhbfibfjavTavUbfkavUbflavUbfmbfnavVbfobfpbfqbfqbfrbfsbftbfubfvbfwbfxbfybfwbfzbfAbfwbfBbfCbfDbfEbfFbfGbfHbfIbfJbfKbfKbfLbfMbfNbfObfPbfQbfRbfSbfSbfSbfSbfSbfSbfSbfTbfUbfVbfVbfVbfVbfVbfVbfVbfVbfWbfXbfYbfZbfVbgabfWbfVbfVbgbbgcbgdbezbgebgfbggbghbgibezbgjbmOaoGbglaoGaaabeCbgmbgnbeCbgobgpbgqbgrbgsbgtbambgubgvbgwbgxbmPbgzbambgAbgBbgCbdEbgDbgEbgFbdEbgGaOdaOdbgHaOdbgIaOdaOdaOdbgJaOdbgKbgLbgKbgLaefaefaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaaaaUVbgMaXIaXOaaaaXLbdIbgNbgObdIbgPbgQbgRbdIbgSbgTbdPaXLaaaaZhaXIbgUaaabfcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqabqaaabccbdRbccbccbccbccbccbccbdRbccaaaaWDbgVbgWbgXbgXbgXbgXbgXbgXbgXbgXbgYbgZbfwbfwbhabhbbhabfwbfwbfwbhcbfwbhdbhebhfbhgbhhbhibhjbhkbhlbhmbhnbfGbhobfIbhpblhbhqbhrbhqbhsbhqbhtbhubhtbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhwbhwbhxbhwbhwbhwbhwbhwbrNbhybfIbhzbezbhAbhBbhCbhDbhEbezbhFbhGaoGaGWaoHaaabhHbhIbhJbhKbhLbhMbhNbhObhPbhQbambhRbhSbhTbhTbhUbhVbambhWbhXbhWbdEbhYbhZbiabdEbibaCgaCgaCgaCgaCgaCgaCgaCgaCgaHjaCgaCgbdFaCgabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqarBbicbidbiebifaXLaXLaXLbdIbigbihbiibdIbdIbdIbijbikbilbdPaXLaXLaXLbimaWBaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabinbiobipbiobiqbiobiobiqbiobipbirbisaWDbgVbitbiubivbiwbixbiybizbiAbgXbiBbiCbiDbiEbiFbiGbiFbiGbiHbiGbiIbfwbiJbiKbiLbiMbiNbiObiPbiQbiRbiSbiTbiUbiVbiWbiXbhqbiYbiZbjabmBbhqbjcbjdbjeabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqbhwbjfbjgbjhbjibjjbjkbjlbhwbjmbjnbjobezbjpbjqbjrbjsbjtbezaoGaoGaoGbjuaoGaaabeCbjvbjwbeCbjxbjybjzbjAbjBbjCbambjDbjEbjFbjGbjHbjIbamaFRbjJaFRbdEbjKbjLbjMbdEdeWavPdfadfcdfbdfdasXdfeanqanqaaaaaaaCgbgLaCgabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaUUaUUbjObjPaXIbjQbjRaaaaaaaXLbjSbjTbjUbdIbdIbjVbdIbdIbgSbjWbjXaXLaaaaaabjYaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqabqaaabccbdRbccbccbccbccbccbccbdRbccaaaaWDbgVbgWbgXbgXbgXbgXbgXbgXbgXbgXbgYbgZbfwbfwbhabhbbhabfwbfwbfwbhcbfwbhdbhebhfbhgbhhbhibhjbhkbhlbhmbhnbfGbhobfIbhpblhbhqbhrbhqbhsbhqbhtbhubhtbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhvbhwbhwbhxbhwbhwbhwbhwbhwbrNbhybfIbhzbezbhAbhBbhCbhDbhEbezbhFbhGaoGaGWaoHaaabhHbhIbhJbbxbhLbhMbhNbhObhPbhQbambhRbhSbhTbhTbhUbhVbambhWbhXbhWbdEbhYbhZbiabdEbibaCgaCgaCgaCgaCgaCgaCgaCgaCgaHjaCgaCgbdFaCgabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqarBbicbidbiebifaXLaXLaXLbdIbigbihbiibdIbdIbdIbijbikbilbdPaXLaXLaXLbimaWBaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabinbiobipbiobiqbiobiobiqbiobipbirbisaWDbgVbitbiubivbiwbixbiybizbiAbgXbiBbiCbiDbiEbiFbiGbiFbiGbiHbiGbiIbfwbiJbiKbiLbiMbiNbiObiPbiQbiRbiSbiTbiUbiVbiWbiXbhqbiYbiZbjabhKbhqbjcbjdbjeabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqbhwbjfbjgbjhbjibjjbjkbjlbhwbjmbjnbjobezbjpbjqbjrbjsbjtbezaoGaoGaoGbjuaoGaaabeCbjvbjwbeCbjxbjybjzbjAbjBbjCbambjDbjEbjFbjGbjHbjIbamaFRbjJaFRbdEbjKbjLbjMbdEdeWavPdfadfcdfbdfdasXdfeanqanqaaaaaaaCgbgLaCgabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaUUaUUbjObjPaXIbjQbjRaaaaaaaXLbjSbjTbjUbdIbdIbjVbdIbdIbgSbjWbjXaXLaaaaaabjYaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabinbiobiobjZbkabkbbkcbkdbkebkfbkgbkhbkbbkibkjbccbgVbgWbkkbklbkmbknbkobkpbkqbkrbksbktbkubkvbkvbkwbkxbkybfwbfwbfwbfwbkzbkAbkBbkCbkDbhabkEbhkbhlbkFbkGbkHbkIbfIbkJbhqbkKbkLbkMbkNbkObkPbkQbkRabqabqbkSbkTbkUbkVbkWbkXbkTbkVbkWbkXbkUbkUbkYabqabqbhwbmRblablbblcblbbldblebhwblfbfIblgbwlbezblibljblkbezbezbllblmaoGblnaoGblobeCbeCbeCbeCbbHbbHbbHblpblqbbHbambambambambamblrblsbambltblubltbdEblvblwblxbdEdffdfhdfgdfgdfjdfkdfkdfkdflabqaaaaaaaaaaefaaaabqaaaaaaaaaaaaaaaaaDaaaaaaaaaaaaaaaaaaaaaaaaabqabqaefblDblEblFblEblGaXOaaaaaaaaaaXLblHbdLblIblJblKblLblMblJblNbdLbdPaXLaaaaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaablOblPblQblRbkbblSblTblSblTblSblTblSbkbblUblVbccbgVblWbgXblXblYblZbmabmbbmcbgXbmdbmebmfbmgbmhbmibmjbmkbmlbmmbmnbmobmpbmqbmrbmsbmtbmubmvbmwbmxbmybmzbmAbiVbfIbmSbhqbmQbmCbmDbmEbhqbmFbmGbjeabqabqbmHboBbopbpVboHbqfbqdbqhbqgbqkbqjbqlbmTabqabqbhwbmUbmVbmWbmXbmYbmZbnabhwbhybnbbncbndbnebnfbnebngbnhbnibnebnebnebnjbnebnkbnlbnmbnnbnebnebnobnkbngbnjbnpbnqbnobnrbnsbntbnubnvbnwbnxbnybnzbnAbnBbnCbnDdfpdfmdftdfqdfxdfudfydeZaoNdflabqaaaaaaaaaaefaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqaefblDblEbnKblEbnLaXOaaaaaaaaaaXLbnMbnNbdJbnObnPbnQbnRbnSbnTbdIbrQaXLaXLaXLaXLbnUaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabiqbkbbkbbipbkbblSblTblSbnVblSblTblSbkbblUblVbccbnWbnXbnYbnZboabobbocbobbiubiubodboebhcbfwbofbogbohboibojbokbolbfwbombonbojbkCboobfwbrXboqborbosbotbiUbkIbfIbkJbhqboubovbowboxbhqboybozbjebkWboAbkWbsbboCboDboEboDboFboDboEboDboGbscbkWboAbkWbhwboIboIboIboJboKboLboMbhwboNboOboPboQboRboSboRboTboRboUboRboRboRboVboRboWboXboYboZboRboRbpabpbbpcboVbpdboVbpebpfbpgbntbphbpibpibpjbpkbpibpidfzdfBdfAdfGdfDdfIdfHdfKdfJdgddfLdgKazDabqaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqbpraaaaaaaaaabqbjRbjRbjObpsaXIaXOaaaaaaaaaaXLaXLblHbdIbdIbdIbptbdIbdIbdIbdIbsebsdbsfaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaablObpwbpxblRbkbblSblTblSblTblSblTblSbkbblUblVbccbpybpzbpAbpBbpCbpDbpDbpEbpFbpBbpGbpHbpIbfwbpJbpKbpLbpMbpNbpObpPbfwbpQbpRbpSbpTbpUbfwbsibpWbpXbpYbpZbfGbqabjnbqbbqcbqcbqcbqcbqcbhtbtPbqebhtbkWbtSbtRbtTboEboEboEboEbqiboEboEboEboEbtZbtYbubbkWbqmbqnbqobqpbqqbqrbqrbqsbhwbqtbqubqvbqwbqxbqybqxbqzbqxbqAbqxbqxbqBbqxbqxbqCbqDbqxbqEbqBbqFbqGbqCbqHbqxbqIbqJbqKbqLbqMbqNbqObqPbqQbqRbpnbqSbqSbqTdgMdgLdgOdgNdgPanqanqanqanqanqanqanqanqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqaaabqYbqZbrabrbbrcbrdbrebrfaXIaXLaXLaXLaXLaXLbrgbrhbrgbrgbribrjbribrkbrkbrlbrmbrnbudaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabrobiobiobjZbrpbkbbrqbkbbrrbrsbkbbrtbkbbkibrubccbgVbrvbrwbrxbrybrzbrAbrBbrCbrxbrDbrEbrFbfwbrGbhabrHbrIbfwbfwbfwbfwbfwbhabrJbrKbfwbfwbiUbrLbrMbiUbiUbzObehbfIbrObqcbrPbumbrRbqcbrSbrTbrUbrVbrWburbrYbrZbsabsabvWbwfbwebvWbvWbsabsabsgbshbwgbkWbhwboIboIboIbsjboIboIboIbhwbskbfIbslbZibsnbsobsnbsmbspbspbspbspbspbspaoGaoGbsqaoGaoGaoGbsrbCiaoGaoGaoGbstaoGbsubsvbswbsxbsybszbsAbsBbqSbsCbsCbsDbqUbsEbjNbntbsFbsGbsHbsIbsJbsJbsKbsLabqaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaabqYbsMbsNaaaabqbsObsPbsQbsRbsSbsTbrgbsUbsVbsWbsXbsYbsZbrgbtabtbbtcbtdbtebtfbtfbtgaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabrobiobiobjZbrpbkbbrqbkbbrrbrsbkbbrtbkbbkibrubccbgVbrvbrwbrxbrybrzbrAbrBbrCbrxbrDbrEbrFbfwbrGbhabrHbrIbfwbfwbfwbfwbfwbhabrJbrKbfwbfwbiUbrLbrMbiUbiUbzObehbfIbrObqcbrPbumbrRbqcbrSbrTbrUbrVbrWburbrYbrZbsabsabvWbwfbwebvWbvWbsabsabsgbshbwgbkWbhwboIboIboIbsjboIboIboIbhwbskbfIbslbZibsnbsobsnbsmbspbspbspbspbspbspaoGaoGbsqaoGaoGaoGbsrbmBaoGaoGaoGbstaoGbsubsvbswbsxbsybszbsAbsBbqSbsCbsCbsDbqUbsEbjNbntbsFbsGbsHbsIbsJbsJbsKbsLabqaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaabqYbsMbsNaaaabqbsObsPbsQbsRbsSbsTbrgbsUbsVbsWbsXbsYbsZbrgbtabtbbtcbtdbtebtfbtfbtgaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabrobiobthbiobiqbiobiobiqbiobipbtibtjaWDbtkbtlbtmbfGbtnbtobtpbtobtqbfGbtrbtsbttbtubtvbtwbtxbtybtzbtwbtAbtBbtwbtvbtvbtCbtvbtDbtEbtFbtGbtHbtvbtIbtJbtKbkJbtLbtMbtNbtObqcbjebjebjebjebkWbwmbtQboEboEboEbtUboEbtVbtWbtXboEboEbwnbuabAkbucbhwbwobuebufbugbuhboIbuibhwbujbfIbukbuldedbunbuobsmbupbuqbwpbusbutbuubuvbuwbuxaoGbuybuzbuAbuBbuCaoGaxcbuDaoGbuEbuFbuGbnEbuHbuHbuHbuIbuJbqSbqSbuKbuLbuMbuNbuObuPbuQbuRbuSbuTbuTbuUbuVbuWbuWbuWbuXdgQbuWbuWbuWbuWbuWbuXbuWbuWbuWbuWbuWbuWbuXbuWbuYbuZbuTbuTbuTbvabvbbvcbvdbvdbvebvfbvgbvhbvibvjbvkbvlbvmbvnbvobvpbvqbvrbvsbvtbvubvvbbXbbXbvwaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqaaabccbdRbccbccbccbccbccbccbdRbccaaaaWDbvxbvybvzbfGbvAbvBbvCbvBbvDbfGbvEbvFbvGbvHbvHbvIbvJbvHbvHbvKbvLbvMbvNbvHbvHbvObvHbvHbvHbvPbvQbvRbvRbvSbvTbvUbvVbqcbyobvXbvYbqcbvZbwabwbbwcbwdboEbtQboEbypbywbwhbwibwjbwibwkbyJbyxbAbbyQbAkbwqbhwbwrbwsbwtbwubwvbhwbhwbhwbhybwwbwxbsmbwybwzbwAbsmbwBbwCbwDbwEbwFbwGbwHbwIbwJbwKbwLbwMbwNbwObwPbwQbwRbwSaoGbsubwTbwUbntbwVbwWbwXbwYbwZbxabxbbxcbxdbqUbxebxfbxgbxhbxiaWCaaaaaabxjbsNabqaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaabxkbxlbsLaaaabqaZhbxmbxnbxobxpbxqbxrbxsbxtbxubxvbxwbxxbxybxzbxAbxBbxCbxDbtfbxEbxFaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqbccabqaaaabqaaabccbxGbccbxHbxIbfebxJbccbxGbccbccaWDbgVbxKbxLbfGbxMbvBbxNbvBbxObfGbxPbxQbxRbxSbxTbxUbxVbxWbxXbxYbxZbyabxTbxTbxTbybbxTbycbydbxVbyebxTbxTbyfbygbyhbvVbqcbyibyjbykbylbymbynbymbymbwdbAjbAebyqbyqbyqbyrbysbytbyubyvbyqbyqbyqbBWbCcbkWbhwbyybyzbyAbyBbyCbhwbyDbyEbyFbyGbwxbsnbyHbyIbCdbsmbyKbyLbyMbyNbspbspaoGaoGbyOaoGaoGaoGbyPbCeaoGaoGbyRbySaoGbyTbwTbyUbntbjNbjNbjNbjNbyVbjNbjNbyWbyXbyYbntbntbyZbzabzbbzcaaabqYbzdaaaabqaaaaaaabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqaaabxkbxlbsLabqbzebzfbzgbzhbzibzjbrgbzkbzlbzmbznbzobzpbrgbzqbzrbzsbrkbztbzubtfbtgaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8593,8 +8600,8 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaabccbcdbcebcebDkbcebDlbDmbDnbDnbDobDnbDpbDqbEJbDsbDtbDubDvbDwbpBbDxbDybDzbDAbDBbDCbDDbDEbDFbDGbDHbDIbDJbBKbDKbDLanHbzKbDMbDNbBQbBRbBSbzKbDObDPbzKbDObDPbzKbDQbfIbkJbqcbqcbDRbqcbqcbqcbDSbDTbDUbqcbFJbtQbDXboEbwibwibDYbDZbEabEbbEcbEdbEebshbFUbEhbEibEjbEkbElbEmbEnbhwbEobhtbEpbbrbhzbspbEqbErbCybEsbCybEtbCybEubEvbCHbEwbExbEybEzbEAbEBbECbEDbEEbEFbEGbEHaoGbEIbwTbHCbCMbEKbELbEMbENbEObCMbEPbEQbERbESbETbEUbEVbEWbEXbEYbEZbFabCMabqabqabqabqabqabqabqaaaabeaaabFbaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdaXOaaaaXLbFebFfbFgbDabFhbFibFjbFkbFlbFmbFnbDaaXLaaaaaaaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqbccbccaWDbccbdQbccaWDbccbccbccaWDbccaWDaWDaWDbnWbnXapfbFoapfapfbFpbFqbFpbFrbFpbFpbFpbFpbBKbBKbFsbFtbBKbBKbBKbFuaoXbzKbFvbFwbBQbFxbzKbzKbFybzKbzKbFzbzKbzKbFAbfIbkJbFBbFCbFDbFEbFFbFGbFDbFDbFHbFIbAkbHDbAdbFKbFLbFMbFNbFObFPbFQbFRbFSbyqbFTbAkbhwbFVbFWbFXbFYbFZbGabhwbGbbhtbhybbrbhzbspbGcbGdbGebGdbGfbGgbGhbGibEvbCHbGjbGkbCHbEvbGlbGmbGnbGobGpbGqbEGbySaoGbGrbGsbGtbGubGvbGwbGxbGybGzbCMbGAbGBbGCbGDbETbGEbGFbGGbGHbGIbGJbGKbCMabqbGLbGLbGLbGLbGLabqaaabFcaaabFbaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdaXOaaaaXLbGMbGNbGObDabGPbGQbGRbGSbGTbGUbGVbDaaXLaaaaaaaUUbjPaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaabGWbGXbGXbGYbGXbGXbGXbGZbGXbGXbHaabqbccbHbdfOdfPapfbINbHJbHdbFpbHebHfbHgbHhbHibHjbFpbHkbHkbHlbHmbHnbHobBKbFubHpbzKbHqbHrbBQbBRbHsbHtbFwbHubHvbHwbHxbzLbzPbfIbkJbFBbHybHzbHAbHAbHAbHAbHAbHBbFIbKRbIObkWbkWbkWbHEbHFbHGbHHbHIbkWbkWbkWbPcbKRbhwbhwbEhbhwbhwbhwbhxbhwbHKbhtbHLbHMbhzbHNbHObHObHObHPbHObHQbHObHRbEvbEvbHSbEvbEvbCHbHTbHUbHVbHWbHXbHYbEGbCIaoGbHZbGsbIabIbbIcbIdbIebIfbIgbIhbIibIjbIkbIlbETbImbInbIobIpbIqbIrbIsbItbIubIvbIwbIxbIxbGLabqaaabFcaaabFbaaaabeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdaXOaaaaXLaXLaXLaXLbDabIybIzbIAbFlbIBbICbIDbDaaXLaaaaZhbIEaWxbIFaWCarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGWbIGbIHbIIbIJbIJbIKbIJbIJbIJbIKbGYbILbccbccdfQbIMapfbFubQZbIPbFpbIQbHfbHgbIRbISbITbFpbIUbIVbIWbIXbBKbBKbBKbFuatjbzKbIYbIZbBQbBRbBQbBQbBQbBQbBQbJabBQbzMbJbbJcbJdbJebJfbJgbJfbJhbJfbJgbJfbJibJjbJkbJlbJmbJnbJobJpbJpbJqbJrbJpbJsbJtbJubJvbJwbJxbJobJybJzbJobJAbJBbJobJCbJDbJEbJFbwxbJGbCybJHbCybJIbCybJJbCybJKbEvbEvbJLbEvbEvbJMbJNbHUbJObECbHXbJPbEGbCIaoGbJQbJRbyUbGubJSbIdbJTbIdbJUbJVbJWbJXbJYbJZbETbKabKbbKcbKdbKebKfbKgbETabqbETbKhbIxbKibGLabqaaabFcaaabFbaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdaXOaaaaaaaaaaaabKjbKkbKlbKlbKmbKnbKmbKlbKlbKobpvaXLaXLbnUbKpbKqaaaarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabKrbKsbKsbKsbKsbKsbKsbKsbKsbKsbKsbKtbKubKvbKudfQbKwapfbKxbKyanEbFpbKzbHfbHgbKAbHfbKBbFpbBKbKCbBKbHmbKDbKEbBKbFuathbzKbKFbHrbKGbKHbKIbKIbKIbKIbKIbKJbKIbKKbygbKLbKMbKNbKObKPbKObKQbSrbKSbKTbKUbKVbKWbKXbKObKYbKZbLabLbbLcbLdbLabLebLfbLgbLhbLibLjbLkbLlbLmbLnbLobLpbLibLqbLrbLsbLtbLubLvbLwbLxbLybLybLzbLAbLwbLBbLCbLDbLEbCHbLFbCHbLGbLHbLIbLJbLKbLLbLMbLNaoGbLObLPbLQbLRbLSbLTbLUbLVbLWbETbLXbLYbLZbMabMbbMcbIobMdbMebMfbMgbMhbMibMjbMkbMlbIxbMmbGLabqaaabFcaaabFbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdbMnaUUaUUaaaaaaaXMbMobMpbMqbKmbMrbKmbMsbMtbMuaXMaaaaZhaXIaXObfcarBarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGWbIGbIHbIIbIJbIJbIKbIJbIJbIJbIKbGYbILbccbccdfQbIMapfbFubQZbIPbFpbIQbHfbHgbIRbISbITbFpbIUbIVbIWbIXbBKbBKbBKbFuatjbzKbIYbIZbBQbBRbBQbBQbBQbBQbBQbJabBQbzMbJbbJcbJdbJebJfbJgbJfbJhbJfbJgbJfbJibCibJkbJjbJmbJlbJpbJnbJnbJqbKYbJrbJsbJtbJubJvbJwbJxbJobJybJzbJobJAbJBbJobJCbJDbJEbJFbwxbJGbCybJHbCybJIbCybJJbCybJKbEvbEvbJLbEvbEvbJMbJNbHUbJObECbHXbJPbEGbCIaoGbJQbJRbyUbGubJSbIdbJTbIdbJUbJVbJWbJXbJYbJZbETbKabKbbKcbKdbKebKfbKgbETabqbETbKhbIxbKibGLabqaaabFcaaabFbaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdaXOaaaaaaaaaaaabKjbKkbKlbKlbKmbKnbKmbKlbKlbKobpvaXLaXLbnUbKpbKqaaaarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabKrbKsbKsbKsbKsbKsbKsbKsbKsbKsbKsbKtbKubKvbKudfQbKwapfbKxbKyanEbFpbKzbHfbHgbKAbHfbKBbFpbBKbKCbBKbHmbKDbKEbBKbFuathbzKbKFbHrbKGbKHbKIbKIbKIbKIbKIbKJbKIbKKbygbKLbKMbKNbKObKPbKObKQbSrbKSbKTbKUbKVbKWbKXbKOcnjbKZbLabLbbLcbLdcpcbLebLfbLgbLhbLibLjbLkbLlbLmbLnbLobLpbLibLqbLrbLsbLtbLubLvbLwbLxbLybLybLzbLAbLwbLBbLCbLDbLEbCHbLFbCHbLGbLHbLIbLJbLKbLLbLMbLNaoGbLObLPbLQbLRbLSbLTbLUbLVbLWbETbLXbLYbLZbMabMbbMcbIobMdbMebMfbMgbMhbMibMjbMkbMlbIxbMmbGLabqaaabFcaaabFbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaZhbFdbMnaUUaUUaaaaaaaXMbMobMpbMqbKmbMrbKmbMsbMtbMuaXMaaaaZhaXIaXObfcarBarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabMvbMwbMxbMybMzbMzbMAbMzbMzbMzbMAbGYbccbccbccdfQbMBapfbMCapfapfbFpbMDbMEbMFbHfbHfbHfbFpbMGbMHbBKbMIbBKbBKbBKbMJbMKbMLbFwbFwbJabMMbMNbFwbFwbFwbFwbMObMPbzLbzPbMQbMRbMSbMSbMTbMUbMVbMSbMSbMWbMWbMXbMYbMWbMZbNabNbbNcbMZbNdbNdbNebNfbNgbNdbNhbNibNjbNkbNhbNhbNlbNmbNnbNhbNobhtbNpbNqbNrbNsbNtbNubNtbNvbNwbCybCybHRbHSbEvbNxbNybNzbNybLDbNAbNBbNCbNDbNEbEGbNFaoGbNGbNHbNIbNJbNKbNLbNMbNNbNObNPbNQbNRbGIbGFbETbNSbNTbNUbNTbNUbNVbNWbETabqbGLbGLbGLbGLbGLabqaaabFcaaabFbaaabFcabfabeabqabeabfabfabeabeaaaaaaaaaaaaarBarBarBbicbNXaWxaWxbNYbrebreaXMbNZbOabObbKmbKnbKmbObbOabOcaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaabMvbGXbGXbGYbGXbGXbGXbGZbGXbGXbOdabqbccbOedfQbOfapfbFuatjbOgbFpbOhbHgbOibOjbKBbHfbFpbOkbOlbBKbIUbOmbOnbBKbFuapdbzKbOobOobJabBRbOpbOpbOqbOrbOsbOtbzKbzKbJbbOubOvbMSbOwbOxbOybOzbOAbOBbOCbODbOEbOFbMWbOGbOHbOIbOJbOKbNdbOLbOMbONbOObOPbNhbOQbORbOSbOTbNhbNhbNhbNhbNhbOUbhtbNpbOVbOWbspbOXbOYbHObOZbPabHObPbbspbSsbTZbEvbEvbEvbEvbEvbPdbPebPfbPgbPhbEGbPiaxhbPjbPkbPlbPmbPnbPobPpbPqbPrbPsbPtbPubPvbPwbPwbPxbPybPzbIpbPAbPBbPCbItbIubIvbPDbPEbPEbGLabqabqbPFabqbPGabqbFcaaaaaaabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaarBaaabPHaXKaXNaXIaXOaaaaXMbPIbOabOabOabPJbOabOabOabPKaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqbccbccaWDbccbdQbccaWDbccbccbccaWDbccaWDaWDaWDdfRbPMbPNbPObPPbPQbFpbPRbPSbOibPTbPUbPVbFpbBKbBKbBKbBKbBKbBKbBKbFuanHbzKbPWbPXbJabBRbFwbFwbPYbFwbPZbQabzKbQbbzPbfIbQcbMSbQdbQebQfbQgbQhbOBbQibQjbQkbQlbQmbQnbQobQobQobQpbQqbQrbQsbQtbQsbQubQvbQwbQxbQybQzbQAbQBbQCbQDbNhbQEbhtbQFbQGbQHbQIbQIbQIbQJbQKbQLbQMbQNbQIbQObQIbQPbQQbQRbQSbQTbEGbEGbQUbEGbEGbEGbNFbQVbQWbQXbQVbCMbCMbCMbCMbCMbQYbNObVpbRabRbbGGbRcbRdbRebRfbInbRgbRhbRibETabqbETbRjbRkbRlbGLabqaaabFcaaabFbaaabRmarBarBarBarBabearBarBarBaaaaaaaaaabqabearBarBarBarBarBaZhaXIaXOaaaaXMbRnbRobRpbOabRqbOabRrbRsbRtaXMaaaaZhaXIaXOarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8614,11 +8621,11 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaacjcaaaaaaabqaaaabqaaabZUbZUbZUceNbZUcjdcjecjfcjgcjhcjicjjchychychscjkbZUcjlcjmbZUcdNcjncjocjpcdTcjqcjrcjscjtcjucjvcjwcjxcjxcjycjxcjzcjAcjBcjBcjCcjDcjEcjFcjGcjHcjIcjJcibciccicciccjKcjLcjMcjNcjOcjPcjQcjRcjScjTcfxcjUbZubZubZubZubZvbZvcjVbZvbZvbZvbZvbZvbZvbZvbZvbZvbZvbZvbZvbZvcjWcjXaoGcjYcjZcfKckackbckcckdckeckfcqcbCMckhckhckickhckjckhckickkckjckjbRickhcklckmcknbCMbCMbCMckockpcjackqckoaaabFcaaaabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqaaackraaaaaaabqaaacksckscktckubZUckvckwckxbZUbZUbZUckyckzchyckAckBbZUbZUbZUckCckDbZUckEckEckEckEckEckEckEckFcjtckGckHckIcjxckJckKckLckMckNckOckPckQckRckSckTckUcgwckVcgycfsckWckXckYckZclaclbclccldclecfxclfclgclhcfxclicljcljcljclkcljcllclmclncljcljclocljcljcljcljclpclqclrclscdocltcluclvclwbVKcfKclxclyclzclAclBclCclDbCMbCMbCMclEbETclFbETclEbETclFclFclGbETclGbCMbCMbCMabqabqabqclHcjaaWCabqabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabeabqclIabqabqabqaaaabqabqbZUcbtclJclKbZUbZUbZUclLbZUbZUbZUbZUbZUbZUbZUclMclNcjlclOclPckEclQclRclSclTclUckEclVclWclXclYclZcjxcmacmbcmccmdcmecmfcmgcmhcmicmjcmicmkcmlckVcmmcmncmocmocmocmocmpcmqcmrcmscmtcfxcmucmvcmwcfxcmxcmycmzcmzcmzcmzcmAcmzcmBcmBcmBcmBcmBcmBcmBcmBcmBcmCbZUcmDasJasJasJaoGasJazocfKcmEcmFcmGclAcqrcqJcqIclAabqabqcmKabqcmLabqcmKabqcmMcmNcmOabqcmOabqabqabqabqaaaaaacmPcjacmQaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaarBaaacmRaaaabqaaaaaaabqaaabZUcmSbZUchnchocjecmTcjecjecmUcmVcmVcmVcmWcmVcmVcmVcmXcmYcmZcnacnbcnccndcnecnfckEcdTcngcnhcnicdTcjxcnjcnkcjxcnlcnmcmgcnncnocnpcnqcnrcmgcnscntcnucmocnvcnwcnxcnycnxcnzcmocnAcnBcnCcnDcnCcfxcfxcnEbZUcmzcnFcnGcnHcnIcnJcmBcnKcnKcnKcnLcnMcnNcnKcmBcmCbZUcnOasIcnPcnQaoGcnRcnScfKcnTcnUcnVclAclBcnWcnXclAabqbGLcnYbETcnYbGLcnYbETcnYbGLcnZbETcoabGLabqaaaabqabqabqcobcjacocabqabqabeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqarBaaacjcaaaabqaaaaaaabqaaabZUbZUbZUbZUbZUbZUbZUbZUbZUcodcoecoecofcogcogcogcogcohcogcogcogcoicojcokcolcomconcoocopcoqcorcoscotcoucovcowcoxcoycozcoAcoBcoCcoDcoEcmgcoFckVcmmcmpcoGcoHcoIcoJcoKcoLcmocoMcoNcoOcoPcmzcdNcjncrFcrvcmzcoRcoScoTcoUcoVcmBcnKcoWcoXcoYcnKcoZcpacmBcpbbZUbZUbZUbZUbZUaoGaoGaoGcfKcfKcfKcpcclAcpdcpecpfcpgabqbGLcphcpicpjbGLcpkcplcpmbGLcpncpocppbGLabqaaaabqaaabCMcpqcprcpscptaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabeaaackrabqabqabqabqabqaaabZUcpucpvcpwcpxcpycpzcpAbZUcodcoecpBcpCcpDcpEcpFcoecpGcpHcpIcoecpJcpKcpLcpMcpNcpOcpPcpQcpRcpScpTcpUcpTcpScpTcpVcpWcpXcpYcpZcqacqbcrVcmicnsckVcrWcmocqdcqecqfcqgcqhcqicqjcqkcqlcqmcqncmzcqocqpcqqcsncmzcqscqtcqucqvcqwcmBcnKcnKcqxcnKcnKcqycqzcmBcmCbZUcqAcqBbZUcqCcqDcqEcqFcqGcqHaoGcsoclAclAcsRclAclAabqbGLcqKcqLcqMbGLcqNcqOcqPbGLcqQcqRcqSbGLabqabqabqabqcptcqTcqUcqVcqWabqabeabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaarBaaackrabqaaaaaaaaaabqaaacqXcqYcqZcracrbcpycrccrdbZUcodcoecrecrfcrgcrhcricrjcrkcrlcrmcoeaovaotcrpcrncrocrscrtcructAcrwcrxcrycrycrycrzcrAcrBcrCcrDcpZcrEctBcrGcmgcrHckVcrIcmocrJcrKcrLcrMcrNcrOcmocrPcrQcrRcrScmzcrTcrUctSctEcmzcrXcrYcrZcsacsbcmBcmBcsccsdcsecsecmBcsfcmBcsgcshcsicsjbZUcskasJasJasJcdKcslbZUcsmcynclAcyqclAcspabqbGLcqKcsqcqKbGLcqNcsrcqNbGLcsscstcssbGLabqaaaabqaaacqWcqUcsucqUcjaaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqabqabeabqckrabqaaaaaaaaaabqaaacqXcsvcrccqZcswcpycsxbZUbZUcsycoecszcsAcszcsBcszcoecszcsCcszcoeckEcsDcsEcsFckEckEcsGcsHcsIcsJcsJcsKcsLcsMcsJcsJcsNcmgcsOcsPcsQcyCcmgcmgcsSckVcsTcmocmocsUcsVcsWcsXcsYcmocsZcnBcfwcfwcmzctacmzctbcmzcmzcfwctcctdcfwcfwctectfctgcthctictjcrqctlcmBctmbZUctnctobZUctpcdKchschyctqctrbZUctscttctuctvctuarAabqbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLabqabqabqabqcjacqUcqUcqUcqWabqbFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaarBaaacmRaaaabqaaaaaaabqaaabZUcmSbZUchnchocjecmTcjecjecmUcmVcmVcmVcmWcmVcmVcmVcmXcmYcmZcnacnbcnccndcnecnfckEcdTcngcnhcnicdTcjxcrjcnkcjxcnlcnmcmgcnncnocnpcnqcnrcmgcnscntcnucmocnvcnwcnxcnycnxcnzcmocnAcnBcnCcnDcnCcfxcfxcnEbZUcmzcnFcnGcnHcnIcnJcmBcnKcnKcnKcnLcnMcnNcnKcmBcmCbZUcnOasIcnPcnQaoGcnRcnScfKcnTcnUcnVctucnXcnWcNmctuabqbGLcnYbETcnYbGLcnYbETcnYbGLcnZbETcoabGLabqaaaabqabqabqcobcjacocabqabqabeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqarBaaacjcaaaabqaaaaaaabqaaabZUbZUbZUbZUbZUbZUbZUbZUbZUcodcoecoecofcogcogcogcogcohcogcogcogcoicojcokcolcomconcoocopcoqcorcoscotcoucovcowcoxcoycozcoAcoBcoCcoDcoEcmgcoFckVcmmcmpcoGcoHcoIcoJcoKcoLcmocoMcoNcoOcoPcmzcdNcjncrFcrvcmzcoRcoScoTcoUcoVcmBcnKcoWcoXcoYcnKcoZcpacmBcpbbZUbZUbZUbZUbZUaoGaoGaoGcfKcfKcfKctkctucpdcpecpfcpgabqbGLcphcpicpjbGLcpkcplcpmbGLcpncpocppbGLabqaaaabqaaabCMcpqcprcpscptaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabeaaackrabqabqabqabqabqaaabZUcpucpvcpwcpxcpycpzcpAbZUcodcoecpBcpCcpDcpEcpFcoecpGcpHcpIcoecpJcpKcpLcpMcpNcpOcpPcpQcpRcpScpTcpUcpTcpScpTcpVcpWcpXcpYcpZcqacqbcrVcmicnsckVcrWcmocqdcqecqfcqgcqhcqicqjcqkcqlcqmcqncmzcqocqpcqqcsncmzcqscqtcqucqvcqwcmBcnKcnKcqxcnKcnKcqycqzcmBcmCbZUcqAcqBbZUcqCcqDcqEcqFcqGcqHaoGcsoctuctucsRctuctuabqbGLcqKcqLcqMbGLcqNcqOcqPbGLcqQcqRcqSbGLabqabqabqabqcptcqTcqUcqVcqWabqabeabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaarBaaackrabqaaaaaaaaaabqaaacqXcqYcqZcracrbcpycrccrdbZUcodcoecrecrfcrgcrhcricCKcrkcrlcrmcoeaovaotcrpcrncrocrscrtcructAcrwcrxcrycrycrycrzcrAcrBcrCcrDcpZcrEctBcrGcmgcrHckVcrIcmocrJcrKcrLcrMcrNcrOcmocrPcrQcrRcrScmzcrTcrUctSctEcmzcrXcrYcrZcsacsbcmBcmBcsccsdcsecsecmBcsfcmBcsgcshcsicsjbZUcskasJasJasJcdKcslbZUcsmcynctucyqctucspabqbGLcqKcsqcqKbGLcqNcsrcqNbGLcsscstcssbGLabqaaaabqaaacqWcqUcsucqUcjaaaabFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqabqabeabqckrabqaaaaaaaaaabqaaacqXcsvcrccqZcswcpycsxbZUbZUcsycoecszcsAcszcsBcszcoecszcsCcszcoeckEcsDcsEcsFckEckEcsGcsHcsIcsJcsJcsKcsLcsMcsJcsJcsNcmgcsOcsPcsQcyCcmgcmgcsSckVcsTcmocmocsUcsVcsWcsXcsYcmocsZcnBcfwcfwcmzctacmzctbcmzcmzcfwctcctdcfwcfwctectfctgcthctictjcrqctlcmBctmbZUctnctobZUctpcdKchschyctqctrbZUctscttdbjctvdbjarAabqbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLbGLabqabqabqabqcjacqUcqUcqUcqWabqbFcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaabqaaaaaaarBaaaclIaaaaaaaaaaaaabqaaacqXctwcqZcswctxcpyctyctzcdOcodcoeczqczpctCctDczJcoectFctGctHcoectIctJctKctLctMctNctOcgrctPcsJctQctRcABctTctUcsJccvcmgctVctWctXctYcmictZcuacubcuccudcuecufcugcuhcuicujcukculcumcuncuocupciccuqcurcusciccutcuucuvciccuwctecuxcuycuzcuAcuBcuCcuDcmBcmCbZUbZUcuEbZUcuFcuGchychycuHcuIcqXabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqaaaabqaaacjacqWcptbCMcptaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqaaaaaaabqaaaaaaabeaaacmRabqaaaaaaaaaabqaaacqXcqXcqZcpycpycqZcqZcuJcdOcodcoecuKcuLcuMcuNcuOcoecuPcuQcuRcuScuTcuUcuVcuWcuXcuYcuZcgrcgscsKcvacvbcvccvdcvecsJchscmgcvfcvgcvhcvicvjcvkcvlckVcvmcvncvocvpcvqcvrcvscvtcvucvvcvwcvxcvycvzcvAcvBcvCcvDcvEcvDcvFcvGcvHcvIcvJcvKcvLcvMcvNcvOcvPcvQcvRcvSbZUcvTcvUcvVcbvctqchychycvWcvXbZUcvYabqaaaaaaaaaabqaaaaaaaaaaaaaaaabqaaaaaaaaaabqaaaaaaaaaaaaabqaaaabqaaaaaaabqaaaabqaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaabqabqaaaaaaarBaaacjcaaaaaaaaaaaaabqaaacqXcvZcqZcwacqZcqZcsxbZUbZUcwbcwccwdcuLcwecuNcwfcwgcwhcwicwjcwkcwlcwmcwncwocwpcwqcwrcwscjAcwtcwucwvcwwcwxcwwcwycwzcmgcwAcwBcwCcwDcmicvkcvlckVcvmcwEcmpcwFcwGcwHcwIcwJcukcwKcwLcwMcwNcwOcwPcwQcwRcihcihcwScwTcwUcwVcwWcwXcwYcwZcxacxbcxccxdcxecmBcmCbZUcxfcxgcxhcsicxicuHcmDchycxjcqXaaaabqaaaaaaaaaabqabqabebFbbFbbFbbFbbFbbFbabebFbbFcbFbbPGabqbFcabqabqabebRmbRmbRmabeabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8627,18 +8634,18 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczmaaaaaaaaaabqaaaaaaaaaabqaaaaaaabqaaaclIaaaaaaabqaaaabqaaacqXcqXcqXbZUbZUcznczobZUbZUcodcoecMbcuLcwdcuNcMXcoecwdcxtcwdcwdczrcoeczscztczuczvcwrczwczxcsJczyczzczAczBczBczBczBczBczBczBczCczDczCczEczFczGczHczIcMYczKczLbZUczMczMczNczMczMczOczPczQcyZczRczSczTczUczVczWcxVczXczYczZcAacAbcrUcfYclPbZUcAccmYcAdbZUcAecfYbZUaaaabqaaaaaaaaaaaaabqaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaabqaaaaaaabqaaaabqaaaabqaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaaacAfcAfcAfcAfcAfabqabqabqcAfcAfcAfcmRcAfaaaarBaaaabqaaaaaaaaaaaabZUbZUbZUbZUbZUcAgcodcwccwdcuLcwecuNcwdcAhcwdcAicwdcwdczrcoecAjcAkcAlcAmcAncAocApcsJcsJcsJcsJczBcAqcArcAscAtcAuczBcAvcAwcAxcAycAzcgxcAAbZUcMZcACcADcAEczMcAFcAGcAHczMcAIcAJcAKcALcPkcANcAOcAPcAQcARcxVcAScATcAUcAVcAWcrUcAXcAYcAZcBackDcBbcAZcBccvWcqXabqabqabqabqabqabqabqabqabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabeabqcBdcBecBecBecBecBfckrcBgcBhcBhcBhcBhcBiabqabqabqabqabqabqabqabqbZUcFRcFScFRbZUcBjcBkcoecBlcBmcxpcBncBocoecxscwdcwdcwdcBpcoecBqcBrcBrcBrcBscBtcBucBvcBwcBxcByczBcBzcBAcBBcBCcBDczBcBEcBFcBGcBHcAzcgxcBIcBJcBKcBJcBJcBJczMcBLcBMcAGcBNcBOcBPcBQcBRcBScBTcBUcBUcBVcAQcxVcBWcATcBXcBYcBZcrUcCacCbbZUcCcchycCdbZUchycCebZUaaaabqaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaDaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcCfcCfcCfcCfcCfaaackraaacCfcCfcCfcCfcCfaaaarBaaaaaaaaaaaaabqabqbZUbZUbZUbZUbZUchycBkcoecCgcChcCicCjcCkcoecClcwdcCmcCncCocoecCpcCqcCrcCscCtcCucCvcBvcCwcCxcCyczBcCzcCAcCBcCCcCDczBcCEcCFczCczCcCGcgxcmmcBJcCHcCIcCJcCKczMcCLcAGcCMczMcCNcCOcCPcxUcCQcCRcPCcCTcCUcCVcxVcCWcCXcCYcCZcBYcrUbZUbZUbZUctmbZUcDabZUbZUbZUbZUabqabqaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcCfcCfcCfcCfcCfaaackraaacCfcCfcCfcCfcCfaaaarBaaaaaaaaaaaaabqabqbZUbZUbZUbZUbZUchycBkcoecCgcChcCicCjcCkcoecClcwdcCmcCncCocoecCpcCqcCrcCscCtcCucCvcBvcCwcCxcCyczBcCzcCAcCBcCCcCDczBcCEcCFczCczCcCGcgxcmmcBJcCHcCIcCJcFoczMcCLcAGcCMczMcCNcCOcCPcxUcCQcCRcPCcCTcCUcCVcxVcCWcCXcCYcCZcBYcrUbZUbZUbZUctmbZUcDabZUbZUbZUbZUabqabqaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabeaaaabqaaaabqabqabqaaacDbaaaabqaaaabqaaaabqaaaarBaaaaaaaaaabqabqaaaabqaefbZUcDcbZUchycBkcoecoecoecoecoecoecoecoecDdcoecoecoecoecDecDfcDgcDhcDicDjcDkcDlcDmcDncDocDpcDqcDrcDscDtcDucDvcDwcDxcDyczCcmlcDzcDAcDBcDCcDDcDDcDEczMcDFcDFcDGczMcgCcCOcDHcxUcxUcxUcxUcxUcxUcxUcxVcxVcxVcDIcxVcxVcrUcAccDJcmYcDKbZUchycDLcDMcDNcDMckscksaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaaacAfcAfcAfcAfcAfabqckrabqcAfcAfcAfcAfcAfabqarBaaaaaaaaaabeaaaaaacDOcDPclJcDQcDRcDQcDScljcljcljcljcljcljcljcljcljcDTcDUcDUcDUcDUcDUcDUcDUcDVcDWcDXcDYcDZcEacEbcEccEdcEecEfcEgcEhcEicEjcEkcElcEmcEncgxcEocEpcEqcErcErcEsczMcEtcEucEuczMcEvcEwcExcEycEzcEAcEBcECcEDcEEcEFcEGcEHcEIcEJcEKcfZcELchychybZUbZUcEMbZUbZUbZUbZUabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcBdcBecBecBecBecBfckrcBgcBhcBhcBhcBhcBiabqaupabqabqabqarBabqabqabqabqbZUcENbZUcdNckDchychycEObZUbZUbZUbZUbZUcEPcEQcDUcERcEScETcEUcEVcDUcEWcEXcEYcBvcEZcFacFbczBcFccFdcFdcFdcFeczBcFfcFgcFhcFicFjcFkcFlcBJcFmcCIcFncFoczMcFpcFqcFrcBNcFscFtcFucFvcFwcFxcFycFzcFAcFBcFCcFDcFBcFEcFFcEKbZUcFGbZUcFHcFHcFIcFJcFKcFLcFMabqabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFNcFOcFNabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcBdcBecBecBecBecBfckrcBgcBhcBhcBhcBhcBiabqaupabqabqabqarBabqabqabqabqbZUcENbZUcdNckDchychycEObZUbZUbZUbZUbZUcEPcEQcDUcERcEScETcEUcEVcDUcEWcEXcEYcBvcEZcFacFbczBcFccFdcFdcFdcFeczBcFfcFgcFhcFicFjcFkcFlcBJcFmcCIcFncWcczMcFpcFqcFrcBNcFscFtcFucFvcFwcFxcFycFzcFAcFBcFCcFDcFBcFEcFFcEKbZUcFGbZUcFHcFHcFIcFJcFKcFLcFMabqabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFNcFOcFNabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcCfcCfcCfcCfcCfaaaclIabqcCfcCfcCfcCfcCfaaaarBaaaaaaaaaabqaaaaaaaaaaaabZUbZUbZUcfZbZUcjncFPcFQbZUcPGcNacNbbZUcFTcFUcFVcFWcFXcFYcFZcGacGbcGccGdcGecBvcGfcGgcGhczBcGicGjcGkcGlcGmczBcGncGocGoczCcGpcGqcGrcGscGtcGucGvcGwczMcGxcGycGzcGAcGBcGCcGDcGEcGFcGGcGHcGIcGIcGJcGKcGLcGMcGNcGOcGPcGQcGRcGScGTcGUcGVcGVcGVcGWcGXabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFOcFNcGYcFNcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaupaaaabqaaaabqaaaabqaaacmRaaaabqaaaabqabqabqabqaupaaaaaaaaaabqaaaaaaaaaaaaabqaaabZUbZUbZUbZUbZUbZUbZUcNOcNPcNQbZUckDcGZcDUcHacHbcHccHdcHecHfcHgcHhcHicBvcBvcHjcBvczBczBczBczBczBczBczBcHkczCczCcHlcHmczGczHcHncHocHocHpcHqczMcHrcHscHtcHucHvcHwcHxcHycHzcHAcHBcHCcHDcHEcHFcHGcHHcHIcHJcHKcHLcHMcHNcHOcHPcHQcHRcHScHTcGXabqabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcHUcFOcHVcHWcHXcFOcHUabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaaacAfcAfcAfcAfcAfabqcHYabqcAfcAfcAfcAfcAfabqarBaaaaaaaaaabeabqcHZcHZcHZcIacHZcHZcHZaaaabqaaaaaabZUcOJcOKcOLbZUcIbcEQcDUcIccIdcHbcIecIfcDUcIgcIhcIicDUcIjcIkcIlcImcIncIocIncIpcIncIqcIocIrcImcIscnscgxcItcBJcIucIvcIwcIucIxcIxcIxcIxcIxcIycxPcIzcEycIAcIAcIBcICcIDcIEcIFcIGcIHcIIcIJcEKcIKcILcIMcEycINcGXcGXcFHcGXcFHarAabqaaaaaaabqaaaaaaabqabqabqaaaaaaaaaaaaaaaabqaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabqaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabqabqcFOcFOcIOcIPcIPcIPcIQcFOcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcBdcBecBecBecBecBfckrcBgcBhcBhcBhcBhcBiabqarBaaaabqabqarBaaacHZcIRcIScIRcITcIRcHZcHZcIacHZcIacHZcHZcPDcPEcPFcjicQKcDUcDUcDUcDUcDUcDUcDUcIUcIVcIWcIXcIYcIZcJacImcJbcJccIncIocIncJdcJecJfcImcJgcnscgxcvmcwEcJhcJicJjcJkcJlcJmcJncJocJpcJqcCOczQcEKcEKcEKcEKcEKcEKcJrcJscJtcJucJvcJwcEKbZUcFGbZUcFHcJxcJycJzcJAcJBarAarAabqabqabqabqabqabqabqaaaabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqcJCcJDcJCcIPcJEcIPcJFcJGcFNabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcCfcCfcCfcCfcCfaaaclIaaacCfcCfcCfcCfcCfaaaaupabqabqaaaarBabqcHZcJHcJIcJJcJKcJHcJLcJMcJNcJOcJPcJQcHZbZUbZUbZUbZUcJRcJScJScJTcJScJUcJVcJWcJXcJYcJZcKacKbcKccKdcKecKfcKgcKfcKfcKhcKicKjcKkcKlcKmcKncFkcKocKpcKqcKrcKscKtcKtcKtcKucKvcJpcgCcCOcKwcEKcKxcKycKzcKAcKBcKCcKBcKDcKEcKFcEKcrUcKGccscfYcFHcFHcFHcFHcFHcKHcKIarAabqaaaaaaaaaaaaaaaabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaabqabqcFOcFOcKJcIPcIPcIPcKKcFOcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcBdcBecBecBecBecBfckrcBgcBhcBhcBhcBhcBiabqarBaaaabqabqarBaaacHZcIRcIScIRcITcIRcHZcHZcIacHZcIacHZcHZcPDcPEcPFcjicQKcDUcDUcDUcDUcDUcDUcDUcIUcIVcIWcIXcIYcIZcJacImcJbcJccIncIocIncJdcJecJfcImcJgcnscgxcvmcwEcJhcJicJjcJkcJlcJmcJncJocJpcJqcCOczQdgSdgSdgSdgSdgSdgScJrcJscJtcJucJvcJwcEKbZUcFGbZUcFHcJxcJycJzcJAcJBarAarAabqabqabqabqabqabqabqaaaabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqabqcJCcJDcJCcIPcJEcIPcJFcJGcFNabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabqcCfcCfcCfcCfcCfaaaclIaaacCfcCfcCfcCfcCfaaaaupabqabqaaaarBabqcHZcJHcJIcJJcJKcJHcJLcJMcJNcJOcJPcJQcHZbZUbZUbZUbZUcJRcJScJScJTcJScJUcJVcJWcJXcJYcJZcKacKbcKccKdcKecKfcKgcKfcKfcKhcKicKjcKkcKlcKmcKncFkcKocKpcKqcKrcKscKtcKtcKtcKucKvcJpcgCcCOcKwdgScKxcKycKzcKAdgTcKCcKBcKDcKEcKFcEKcrUcKGccscfYcFHcFHcFHcFHcFHcKHcKIarAabqaaaaaaaaaaaaaaaabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaabqabqcFOcFOcKJcIPcIPcIPcKKcFOcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBaaaaaaabqabqabqaaaaaacKLabqaaaaaaabqabqaaaaaaarBaaaaaaaaaabeaaacHZcKMcKNcKOcKPcKMcKMcKQcKRcKScKTcKUcHZaaaaaaaaacrUcrUcrUcrUcrUbZUcKVcDUcDUcKWcKXcRocDUcKZcLacLbcImcLccIocIncIocIncLdcLecLfcLgcLhcLicLjcLkcIxcIxcLlcLmcLncLocLpcLqcLrcJpcLscLtcLucGXcKxcKycLvcLvcLwcLxcLycLzcJucLAcEKcdNcLBceNchycLCbZUabqabqabqabqabqabqabqaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcHUcFOcLDcLEcLFcFOcHUabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaupaaaaaaaaaaaaaaaaaaaaacKLaaaaaaaaaaaaabqaaaaaaaupaaaaaaaaaarBabqcHZcLGcLHcLIcLJcLKcLLcLMcLNcLOcLPcLQcLRcLScLScLScLRcLTcLUcLVcHZcLWcLXcDUcLYcLZcMacSBcRUcRUcRUcRUcImcIncIocIncMccIncMdcMecMfcImcMgcMhcgxcmmcIxcMicMjcMkcLocLocMlcMmcMncJpcMocMpcMqcEKcKxcKycLvcMrcKBcMscKBcMtcMucMvcEKcMwchyceNchycMxbZUabqaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFOcFNcMycFNcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabearBarBarBaaaaaaaaacKLaaaaaaaaaarBarBarBauparBabqabqaaaarBaaacIacMzcMAcMBcMCcMDcMEcMFcMGcMHcMIcMJcMKcMLcMMcMNcMOcMPcMBcMQcMRcMScMTcMUcMScMVcMWcWGcSCcWIcWHcYocRUcImcImcImcImcImcImcNccImcImbZUcNdcgxcmmcIxcNecMjcLocLpcLocNfcNgcNhcNicNjcNkcNlcNmcNncNncNncNncNncNocNncNpcNqcNrcEKchychycNschybZUbZUbZUabqabqaaaaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFNcFOcFNabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaupaaaaaaaaaaaaaaaaaaaaacKLaaaaaaaaaaaaabqaaaaaaaupaaaaaaaaaarBabqcHZcLGcLHcLIcLJcLKcLLcLMcLNcLOcLPcLQcLRcLScLScLScLRcLTcLUcLVcHZcLWcLXcDUcLYcLZcMacSBcRUcRUcRUcRUcImcIncIocIncMccIncMdcMecMfcImcMgcMhcgxcmmcIxcMicMjcMkcLocLocMlcMmcMncJpcMocMpcMqdgScKxcKycLvcMrdgTcMscKBcMtcMucMvcEKcMwchyceNchycMxbZUabqaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFOcFNcMycFNcFOabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBabearBarBarBaaaaaaaaacKLaaaaaaaaaarBarBarBauparBabqabqaaaarBaaacIacMzcMAcMBcMCcMDcMEcMFcMGcMHcMIcMJcMKcMLcMMcMNcMOcMPcMBcMQcMRcMScMTcMUcMScMVcMWcWGcSCcWIcWHcYocRUcImcImcImcImcImcImcNccImcImbZUcNdcgxcmmcIxcNecMjcLocLpcLocNfcNgcNhcNicNjcNkcNldgVdgUdgUdgUdgUdgUcNocNncNpcNqcNrcEKchychycNschybZUbZUbZUabqabqaaaaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqcFNcFOcFNabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaabqaaaaaaaaaarBabqcNtabqarBaaaaaaabqaaaaaaabqaaaabqabqabqaaacHZcNucNvcNwcNxcNycNzcNAcNBcNCcNDcNEcHZcIacIacIacHZcNFcNGcNHcHZcNIcNJcDUcNKcNLcNMcNNdegdeidehdejcRUcNRcmVcNScmWcmVcNTcNUcDJcmZcNVcNWcNXcBIcIxcNYcNZcOacOacOacObcOccOdcOecOfcOgcOhcOicOjcOkcOlcOmcOncOocOpcOqcOrcOscOtcmYcmYcOucOvcOwcOxbZUbZUbZUcksaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqabqabqabqabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaarBaaaabqaaaarBaaaaaaabqabqabqabqaaaaaaaaaabqabqcHZcOycOzcKMcOAcOycOBcODcOCcOEcOFcOGcHZcOHaaaaaacrUcrUcrUcrUcrUbZUcOIcDUcDUcDUcDUcDUcRUdeldekdemcRUcOMbZUbZUbZUbZUbZUbZUbZUbZUczIcONcOOcOPcOQcORcOScOTcOUcOVcOWcLpcOXcOYcOZcPacPbcPccPdcPecPfcPgcPhcPicOpclNcPjbZUbZUbZUbZUbZUdencPlcPmclJcPnclJcPoabqabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarBarBarBarBarBaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaacHZcPpcPqcKMcPqcPrcPscKMcKMcPtcKMcKMcHZabqabqabqbZUcjncfZcPucPvcPwcPxcmYcPycPzcPAcPBcRUdepdeodeqcRUcOMbZUcPHcPIcPJbZUcPKcPLcPMbZUcPNcPOcPPcIxcPQcPRcPScPTcPUcPVcLpcPWcIxcPXcPYciccPccPZcQacQbcQccQdcQecOpchycQfbZUcQgcQhcQibZUcQjcQkcQlbZUbZUbZUcksaaaabqaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8650,7 +8657,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabeabqabqabqaaaaaaaaaabqabqabqaaaaaaaaaabqaaaaaaaaacRhcUgcUhcUicUjcUkcUlcUmcRhcUncRhcUocUpcUqcUrcUscTHcTHcUtcUucUvcUwcUxcUycSYcUzcTacRtcSocUAcUBcUCcUDcUEcUFcUGbZUcTjbZUabqabqcTXcUHcTXabqaaacTZcUIbZUchychychycUJcUKcctcULbZUcqXcQWcUecUMcUeabqaaaabqaaaaaaabqabqabqabqarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabeaaaaaaaaaaaaaaaabqaaaaaaaaaabqaaaaaaaaacRhcTycUNcRhcUOcUPcUQcURcUScUTcRhcUUcUVcUWcUXcUYcUZcVacVbcSWcTacRtcVccVdcVecVfcVgcUwcVhcVicVjcVkcVkcVlcVmcVkbZUaefabqaaaaaacTXcVncTXaaaaaacTZcSvbZUcVocVpcVqbZUcVrcVscVqbZUaaaabqcUecUfcUeabqaaaabqaaaaaaabqabqaaaaaaarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfabeaaaaaaabqabeabfabeabqabeabeabeabqcSOcSOcSOcRhcRhcRhcRhcVtcVucRhcRhcRhcVvcVwcVxcUXcVycVzcVAcSOcSOcTacRtcRtcRtcSYcSZcTacRtcVBcVCcVDcVEabqabqaaaaaaabqaefabqaaacVFcVGcVHcVGcVIaaacTZcSvbZUbZUbZUbZUbZUbZUbZUbZUbZUaaaabqaaacVJaaaabqabqabqabqabqabqaaaaaaabqarBabqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfaaaaaacVKcVLcVMcSOcVNcVOcVPcVQcVRcVScSOcVTcVUcVVcVWcUXcUYcUZcVacVXcSOcVYcRtcVZcWacWbcWccWdcWacWecRtcWfcVkaaaabqabqabqabqabqabqabqcVGcWgcWhcWicVGaaacTZcWjcWkcWkcWkcWlcWmcTZaaaabqaaaaaaabqaaacVJaaaabqabqaaaaaaaaaabqaaaaaaaaaaupaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfaaaaaacVKcVLcVMcSOcVNcVOcVPcVQcVRcVScSOcVTcVUcVVcVWcUXcUYcUZcVacVXcSOcVYcRtcVZcWacWbcrrcWdcWacWecRtcWfcVkaaaabqabqabqabqabqabqabqcVGcWgcWhcWicVGaaacTZcWjcWkcWkcWkcWlcWmcTZaaaabqaaaaaaabqaaacVJaaaabqabqaaaaaaaaaabqaaaaaaaaaaupaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfaaaaaacVKcWncVMcWocWpcWpcWpcWqcWrcWscWtcWucWvcWucWwcWpcWxcWwcWycWzcSVcWAcWBcWCcWBcWBcWBcWBcWBcWCcWBcWDcVEaaaabqaaaaaaabqaaaaaaaaacVGcWEcWFdezdeAcyncTZcTZcTZcTZcTZciccSvcTZabqabqaaaaaaaaaaaacWJcWKcWKcWKcWKcWKcWKcWKcWKcWKcWLaaaaaaaaaaaaaaaaaaarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfaaaaaacVKcWncWMcVRcWNcWOcWNcWPcWQcWRcWScWTcWUcWVcWVcWWcWVcWVcWXcWYcSOcWZcXacXbcXacXacXccXacXacXdcXecXfcVkabqabqaaacVGcVGcVGcVGcVGcVGcXgcXhcXicVGcVGcVGcVGcVGcVGcTZciccSvcTZabqabqabqabqabqabqabqabqabqaaaabqaaaaaaaaaaaaaaacVJaaaaaaabqaaaaaaaaaaupaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfabqaaacVKcXjcVMcVRcWNcWNcWNcXkcSOcSOcSOcSOcXlcXmcUXcXncUXcXmcXocSOcSOcVEcXpcVEcXpcVEcVEcVEcXpcXpcVEcVEcVkaaaabqabqcVGcXqcXrcXscXtcVGcXucXvcVGcVGcXwcXxcXycXzcVGcTZciccSvcTZabqcXAcXBcXCcXBcXCcXBcXDabqauparBaupabqabqabqabqcVJabqabqabqabqabqabearBarBaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/_maps/metastation.dm b/_maps/metastation.dm index 3cbc8cdc16d..2010b25d501 100644 --- a/_maps/metastation.dm +++ b/_maps/metastation.dm @@ -25,9 +25,10 @@ z7 = empty space #define MAP_FILE "MetaStation.v41A.II.dmm" #define MAP_NAME "MetaStation" + #define MAP_TRANSITION_CONFIG list(MAIN_STATION = CROSSLINKED, CENTCOMM = SELFLOOPING, TELECOMMS = CROSSLINKED, DERELICT = CROSSLINKED, MINING = CROSSLINKED, EMPTY_AREA = CROSSLINKED, EMPTY_AREA_2 = CROSSLINKED) #elif !defined(MAP_OVERRIDE) #warn a map has already been included, ignoring MetaStation. -#endif \ No newline at end of file +#endif diff --git a/_maps/test_away_missions.dm b/_maps/test_away_missions.dm index 59ca6167d68..e5c1f0d192e 100644 --- a/_maps/test_away_missions.dm +++ b/_maps/test_away_missions.dm @@ -10,12 +10,13 @@ #include "map_files\RandomZLevels\spacehotel.dmm" #include "map_files\RandomZLevels\stationCollision.dmm" #include "map_files\RandomZLevels\wildwest.dmm" - + #include "map_files\RandomZLevels\evil_santa.dmm" #define MAP_FILE "beach.dmm" #define MAP_NAME "Away Missions Test" + #define MAP_TRANSITION_CONFIG list(AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED, AWAY_MISSION = UNAFFECTED) #elif !defined(MAP_OVERRIDE) #warn a map has already been included. -#endif \ No newline at end of file +#endif diff --git a/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm index d837af98739..8b871847b23 100644 --- a/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm +++ b/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm @@ -10,6 +10,7 @@ var/obj/machinery/atmospherics/unary/heat_exchanger/partner = null var/update_cycle + burn_state = LAVA_PROOF /obj/machinery/atmospherics/unary/heat_exchanger/update_icon() if(node) diff --git a/code/LINDA/LINDA_fire.dm b/code/LINDA/LINDA_fire.dm index 14f8ab20998..d5ab43d4ab3 100644 --- a/code/LINDA/LINDA_fire.dm +++ b/code/LINDA/LINDA_fire.dm @@ -126,6 +126,9 @@ var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE for(var/direction in cardinal) if(!(location.atmos_adjacent_turfs & direction)) + var/turf/simulated/wall/W = get_step(src, direction) + if(istype(W)) + W.adjacent_fire_act(W, radiated_temperature) continue var/turf/simulated/T = get_step(src, direction) if(istype(T) && T.active_hotspot) diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 339b00714f7..d2988a6474f 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -114,7 +114,4 @@ // Atmos pipe limits #define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at. -#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at. - -// Sound Limits -#define SOUND_MINIMUM_PRESSURE 10 \ No newline at end of file +#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at. \ No newline at end of file diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index f6ddb6a5a6a..cbd39a49a21 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -270,6 +270,19 @@ // Macro to get the current elapsed round time, rather than total world runtime #define ROUND_TIME (round_start_time ? (world.time - round_start_time) : 0) +// Macro that returns true if it's too early in a round to freely ghost out +#define TOO_EARLY_TO_GHOST (config && (ROUND_TIME < (config.round_abandon_penalty_period))) + // Used by radios to indicate that they have sent a message via something other than subspace #define RADIO_CONNECTION_FAIL 0 #define RADIO_CONNECTION_NON_SUBSPACE 1 + +//Fire stuff, for burn_state +#define LAVA_PROOF -2 +#define FIRE_PROOF -1 +#define FLAMMABLE 0 +#define ON_FIRE 1 + +// Sound +#define SOUND_MINIMUM_PRESSURE 10 +#define FALLOFF_SOUNDS 0.5 \ No newline at end of file diff --git a/code/__DEFINES/zlevel.dm b/code/__DEFINES/zlevel.dm new file mode 100644 index 00000000000..e69de29bb2d diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 0852622f2c6..5c11daabdba 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -435,14 +435,14 @@ /proc/SecondsToTicks(var/seconds) return seconds * 10 -proc/pollCandidates(var/Question, var/be_special_type, var/antag_age_check = 0, var/poll_time = 300) +proc/pollCandidates(var/Question, var/be_special_type, var/antag_age_check = 0, var/poll_time = 300, var/ignore_respawnability = 0) var/roletext = be_special_type ? get_roletext(be_special_type) : null var/list/mob/dead/observer/candidates = list() var/time_passed = world.time if(!Question) Question = "Would you like to be a special role?" - for(var/mob/dead/observer/G in player_list) + for(var/mob/dead/observer/G in (ignore_respawnability ? player_list : respawnable_list)) if(!G.key || !G.client) continue if(be_special_type) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 29ccb098cb9..53285c92fa1 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -58,12 +58,41 @@ return 0 //Checks for specific types in a list -/proc/is_type_in_list(var/atom/A, var/list/L) +/proc/is_type_in_list(atom/A, list/L) + if(!L || !L.len || !A) + return 0 for(var/type in L) if(istype(A, type)) return 1 return 0 +//Checks for specific types in specifically structured (Assoc "type" = TRUE) lists ('typecaches') +/proc/is_type_in_typecache(atom/A, list/L) + if(!L || !L.len || !A) + return 0 + return L[A.type] + +//Like typesof() or subtypesof(), but returns a typecache instead of a list +/proc/typecacheof(path, ignore_root_path) + if(ispath(path)) + var/list/types = ignore_root_path ? subtypesof(path) : typesof(path) + var/list/L = list() + for(var/T in types) + L[T] = TRUE + return L + else if(islist(path)) + var/list/pathlist = path + var/list/L = list() + if(ignore_root_path) + for(var/P in pathlist) + for(var/T in subtypesof(P)) + L[T] = TRUE + else + for(var/P in pathlist) + for(var/T in typesof(P)) + L[T] = TRUE + return L + //Removes any null entries from the list /proc/listclearnulls(list/list) if(istype(list)) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index e1965cf701e..889a0824f35 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -270,4 +270,75 @@ proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=nul . = 0 break if(progress) - qdel(progbar) \ No newline at end of file + qdel(progbar) + +/proc/admin_mob_info(mob/M, mob/user = usr) + if(!ismob(M)) + to_chat(user, "This can only be used on instances of type /mob") + return + + var/location_description = "" + var/special_role_description = "" + var/health_description = "" + var/gender_description = "" + var/turf/T = get_turf(M) + + //Location + if(isturf(T)) + if(isarea(T.loc)) + location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])" + else + location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])" + + //Job + antagonist + if(M.mind) + special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]" + else + special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;" + + //Health + if(isliving(M)) + var/mob/living/L = M + var/status + switch(M.stat) + if(CONSCIOUS) + status = "Alive" + if(UNCONSCIOUS) + status = "Unconscious" + if(DEAD) + status = "Dead" + health_description = "Status = [status]" + health_description += "
Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]" + else + health_description = "This mob type has no health to speak of." + + //Gener + switch(M.gender) + if(MALE, FEMALE) + gender_description = "[M.gender]" + else + gender_description = "[M.gender]" + + to_chat(user, "Info about [M.name]: ") + to_chat(user, "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]") + to_chat(user, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];") + to_chat(user, "Location = [location_description];") + to_chat(user, "[special_role_description]") + to_chat(user, "(PM) (PP) (VV) (SM) (FLW) (CA)") + +// Gets the first mob contained in an atom, and warns the user if there's not exactly one +/proc/get_mob_in_atom_with_warning(atom/A, mob/user = usr) + if(!istype(A)) + return null + if(ismob(A)) + return A + + . = null + for(var/mob/M in A) + if(!.) + . = M + else + to_chat(user, "Multiple mobs in [A], using first mob found...") + break + if(!.) + to_chat(user, "No mob located in [A].") diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index b17cda4e560..e56ed3a4310 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -389,4 +389,41 @@ proc/checkhtml(var/t) /proc/macro2html(text) var/static/regex/text_macro = new("(\\xFF.)(.*)$") - return text_macro.Replace(text, /proc/replace_text_macro) \ No newline at end of file + return text_macro.Replace(text, /proc/replace_text_macro) + +/proc/dmm_encode(text) + // First, go through and nix out any of our escape sequences so we don't leave ourselves open to some escape sequence attack + // Some coder will probably despise me for this, years down the line + + var/list/repl_chars = list("#?qt;", "#?lbr;", "#?rbr;") + for(var/char in repl_chars) + var/index = findtext(text, char) + var/keylength = length(char) + while(index) + log_debug("Bad string given to dmm encoder! [text]") + // Replace w/ underscore to prevent "{4;" from cheesing the radar + // Should probably also use canon text replacing procs + text = copytext(text, 1, index) + "_" + copytext(text, index+keylength) + index = findtext(text, char) + + // Then, replace characters as normal + var/list/repl_chars_2 = list("\"" = "#?qt;", "{" = "#?lbr;", "}" = "#?rbr;") + for(var/char in repl_chars_2) + var/index = findtext(text, char) + var/keylength = length(char) + while(index) + text = copytext(text, 1, index) + repl_chars_2[char] + copytext(text, index+keylength) + index = findtext(text, char) + return text + + +/proc/dmm_decode(text) + // Replace what we extracted above + var/list/repl_chars = list("#?qt;" = "\"", "#?lbr;" = "{", "#?rbr;" = "}") + for(var/char in repl_chars) + var/index = findtext(text, char) + var/keylength = length(char) + while(index) + text = copytext(text, 1, index) + repl_chars[char] + copytext(text, index+keylength) + index = findtext(text, char) + return text diff --git a/code/__HELPERS/timed_alerts.dm b/code/__HELPERS/timed_alerts.dm deleted file mode 100644 index 97e92900288..00000000000 --- a/code/__HELPERS/timed_alerts.dm +++ /dev/null @@ -1,37 +0,0 @@ -/client/var/timed_alert/timed_alert - -/client/proc/timed_alert(question as text, title as text, default as text, time = 300, \ - choice1 as text, choice2 as text, choice3 as text) - - if(timed_alert) del(timed_alert) - var/timed_alert/ref_alert = new - timed_alert = ref_alert - - var/ref_result - - ref_result = ref_alert.timed_alert(src, question, title, time, choice1, choice2, choice3) - if(!ref_result) ref_result = default - - if(ref_alert) del(ref_alert) - - return ref_result - - -/mob/proc/timed_alert(question as text, title as text, default as text, time as num, \ - choice1 as text, choice2 as text, choice3 as text) - - if(client) return client.timed_alert(question, title, default, time, choice1, choice2, choice3) - return - - - -/timed_alert/proc/timed_alert(client/ref_client, question, title, time, choice1, choice2, choice3) - if(!ref_client) return - spawn (time) del(src) // When src is deleted, the proc ends immediately. The alert itself closes. - - var/ref_answer - ref_answer = alert(ref_client, question, title, choice1, choice2, choice3) - - if(!ref_client || !ref_answer) return - else return ref_answer - diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index b6dc1c58b8f..644740c9e20 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -22,6 +22,7 @@ var/global/list/spirits = list() //List of all the spirits, including Masks var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player var/global/list/respawnable_list = list() //List of all mobs, dead or in mindless creatures that still be respawned. +var/global/list/non_respawnable_keys = list() //List of ckeys that are excluded from respawning for remainder of round. var/global/list/simple_animal_list = list() //List of all simple animals, including clientless var/global/list/snpc_list = list() //List of all snpc's, including clientless diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm index 1bc335d827a..5fbe701ec2a 100644 --- a/code/_globalvars/mapping.dm +++ b/code/_globalvars/mapping.dm @@ -12,7 +12,8 @@ var/list/diagonals = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) //Was list("3" = 30, "4" = 70). //Spacing should be a reliable method of getting rid of a body -- Urist. //Go away Urist, I'm restoring this to the longer list. ~Errorage -var/list/accessable_z_levels = list(1,3,4,5,6,7) //Keep this to six maps, repeating z-levels is okay if needed +// TODO: Tie into space manager +var/list/accessable_z_levels = list(ZLEVEL_STATION,ZLEVEL_TELECOMMS,ZLEVEL_ENGI,ZLEVEL_ASTEROID,ZLEVEL_DERELICT,ZLEVEL_EMPTY) //Keep this to six maps, repeating z-levels is okay if needed var/global/list/global_map = null //list/global_map = list(list(1,5),list(4,3))//an array of map Z levels. @@ -25,7 +26,8 @@ var/global/list/global_map = null //3 - AI satellite //5 - empty space -var/shuttle_z = 2 //default +// TODO: Tie into space manager +var/shuttle_z = ZLEVEL_CENTCOMM //default var/list/monkeystart = list() var/list/wizardstart = list() diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 543f02e8a79..f6b0e839e73 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -165,7 +165,7 @@ The box in your backpack has an oxygen tank and gas mask in it." name = "Too Cold" desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit." icon_state = "cold" - + /obj/screen/alert/cold/drask name = "Cold" desc = "You're breathing supercooled gas! It's stimulating your metabolism to regenerate damaged tissue." @@ -400,8 +400,7 @@ so as to remain in compliance with the most up-to-date laws." return usr.client.Click(master, location, control, params) /obj/screen/alert/Destroy() - ..() severity = 0 master = null screen_loc = "" - return QDEL_HINT_QUEUE + return ..() diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 8ab49788e5b..fd0c91ded3a 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -63,9 +63,8 @@ var/severity = 0 /obj/screen/fullscreen/Destroy() - ..() severity = 0 - return QDEL_HINT_HARDDEL_NOW + return ..() /obj/screen/fullscreen/brute icon_state = "brutedamageoverlay" diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 403d28ab774..3f5ea2dcb94 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -321,7 +321,7 @@ mymob.healths = new /obj/screen/healths() infodisplay += mymob.healths - mymob.healthdoll = new /obj/screen/healthdoll() + mymob.healthdoll = new() infodisplay += mymob.healthdoll mymob.pullin = new /obj/screen/pull() diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm index c6bbbd27ae2..6c69063e0b8 100644 --- a/code/_onclick/hud/monkey.dm +++ b/code/_onclick/hud/monkey.dm @@ -102,7 +102,7 @@ mymob.healths = new /obj/screen/healths() infodisplay += mymob.healths - mymob.healthdoll = new /obj/screen/healthdoll() + mymob.healthdoll = new() infodisplay += mymob.healthdoll mymob.pullin = new /obj/screen/pull() diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index dc59cf16097..6fe0e4a8532 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -468,3 +468,4 @@ name = "health doll" icon_state = "healthdoll_DEAD" screen_loc = ui_healthdoll + var/list/cached_healthdoll_overlays = list() // List of icon states (strings) for overlays diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 869ee83ff9c..d04abfe5a87 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -25,6 +25,21 @@ return var/list/modifiers = params2list(params) + if(check_rights(R_ADMIN, 0)) // Admin click shortcuts + var/mob/M + if(modifiers["shift"] && modifiers["ctrl"]) + client.debug_variables(A) + return + if(modifiers["ctrl"]) + M = get_mob_in_atom_with_warning(A) + if(M) + client.holder.show_player_panel(M) + return + if(modifiers["shift"] && modifiers["middle"]) + M = get_mob_in_atom_with_warning(A) + if(M) + admin_mob_info(M) + return if(modifiers["shift"]) ShiftClickOn(A) return diff --git a/code/_onclick/oldcode.dm b/code/_onclick/oldcode.dm deleted file mode 100644 index a68f9668e78..00000000000 --- a/code/_onclick/oldcode.dm +++ /dev/null @@ -1,375 +0,0 @@ -/atom/DblClick(location, control, params) //TODO: DEFERRED: REWRITE - if(!usr) return - - // ------- TIME SINCE LAST CLICK ------- - if(world.time <= usr:lastDblClick+1) - return - else - usr:lastDblClick = world.time - - //Putting it here for now. It diverts stuff to the mech clicking procs. Putting it here stops us drilling items in our inventory Carn - if(istype(usr.loc,/obj/mecha)) - if(usr.client && (src in usr.client.screen)) - return - var/obj/mecha/Mech = usr.loc - Mech.click_action(src,usr) - return - - // ------- DIR CHANGING WHEN CLICKING ------ - if( iscarbon(usr) && !usr.buckled ) - if( src.x && src.y && usr.x && usr.y ) - var/dx = src.x - usr.x - var/dy = src.y - usr.y - - if(dy || dx) - if(abs(dx) < abs(dy)) - if(dy > 0) usr.dir = NORTH - else usr.dir = SOUTH - else - if(dx > 0) usr.dir = EAST - else usr.dir = WEST - else - if(pixel_y > 16) usr.dir = NORTH - else if(pixel_y < -16) usr.dir = SOUTH - else if(pixel_x > 16) usr.dir = EAST - else if(pixel_x < -16) usr.dir = WEST - - - - - // ------- AI ------- - else if(istype(usr, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/ai = usr - if(ai.control_disabled) - return - - // ------- CYBORG ------- - else if(istype(usr, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/bot = usr - if(bot.lockcharge) return - ..() - - - // ------- SHIFT-CLICK ------- - - if(params) - var/parameters = params2list(params) - - if(parameters["shift"]){ - if(!isAI(usr)) - ShiftClick(usr) - else - AIShiftClick(usr) - return - } - - // ------- ALT-CLICK ------- - - if(parameters["alt"]){ - if(!isAI(usr)) - AltClick(usr) - else - AIAltClick(usr) - return - } - - // ------- CTRL-CLICK ------- - - if(parameters["ctrl"]){ - if(!isAI(usr)) - CtrlClick(usr) - else - AICtrlClick(usr) - return - } - - // ------- MIDDLE-CLICK ------- - - if(parameters["middle"]){ - if(!isAI(usr)) - MiddleClick(usr) - return - } - - // ------- THROW ------- - if(usr.in_throw_mode) - return usr:throw_item(src) - - // ------- ITEM IN HAND DEFINED ------- - var/obj/item/W = usr.get_active_hand() -/* Now handled by get_active_hand() - // ------- ROBOT ------- - if(istype(usr, /mob/living/silicon/robot)) - if(!isnull(usr:module_active)) - W = usr:module_active - else - W = null -*/ - // ------- ATTACK SELF ------- - if(W == src && usr.stat == 0) - W.attack_self(usr) - if(usr.hand) - usr.update_inv_l_hand(0) //update in-hand overlays - else - usr.update_inv_r_hand(0) - return - - // ------- PARALYSIS, STUN, WEAKENED, DEAD, (And not AI) ------- - if(((usr.paralysis || usr.stunned || usr.weakened) && !istype(usr, /mob/living/silicon/ai)) || usr.stat != 0) - return - - // ------- CLICKING STUFF IN CONTAINERS ------- - if((!( src in usr.contents ) && (((!( isturf(src) ) && (!( isturf(src.loc) ) && (src.loc && !( isturf(src.loc.loc) )))) || !( isturf(usr.loc) )) && (src.loc != usr.loc && (!( istype(src, /obj/screen) ) && !( usr.contents.Find(src.loc) )))))) - if(istype(usr, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/ai = usr - if(ai.control_disabled || ai.malfhacking) - return - else - return - - // ------- 1 TILE AWAY ------- - var/t5 - // ------- AI CAN CLICK ANYTHING ------- - if(istype(usr, /mob/living/silicon/ai)) - t5 = 1 - // ------- CYBORG CAN CLICK ANYTHING WHEN NOT HOLDING STUFF ------- - else if(istype(usr, /mob/living/silicon/robot) && !W) - t5 = 1 - else - t5 = in_range(src, usr) || src.loc == usr - -// to_chat(world, "according to dblclick(), t5 is [t5]") - - // ------- ACTUALLY DETERMINING STUFF ------- - if(((t5 || (W && (W.flags & USEDELAY))) && !( istype(src, /obj/screen) ))) - - // ------- ( CAN USE ITEM OR HAS 1 SECOND USE DELAY ) AND NOT CLICKING ON SCREEN ------- - - if(usr.next_move < world.time) - usr.prev_move = usr.next_move - usr.next_move = world.time + 10 - else - // ------- ALREADY USED ONE ITEM WITH USE DELAY IN THE PREVIOUS SECOND ------- - return - - // ------- DELAY CHECK PASSED ------- - - if((src.loc && (get_dist(src, usr) < 2 || src.loc == usr.loc))) - - // ------- CLICKED OBJECT EXISTS IN GAME WORLD, DISTANCE FROM PERSON TO OBJECT IS 1 SQUARE OR THEY'RE ON THE SAME SQUARE ------- - - var/direct = get_dir(usr, src) - var/obj/item/weapon/dummy/D = new /obj/item/weapon/dummy( usr.loc ) - var/ok = 0 - if( (direct - 1) & direct) - - // ------- CLICKED OBJECT IS LOCATED IN A DIAGONAL POSITION FROM THE PERSON ------- - - var/turf/Step_1 - var/turf/Step_2 - switch(direct) - if(5.0) - Step_1 = get_step(usr, NORTH) - Step_2 = get_step(usr, EAST) - - if(6.0) - Step_1 = get_step(usr, SOUTH) - Step_2 = get_step(usr, EAST) - - if(9.0) - Step_1 = get_step(usr, NORTH) - Step_2 = get_step(usr, WEST) - - if(10.0) - Step_1 = get_step(usr, SOUTH) - Step_2 = get_step(usr, WEST) - - else - if(Step_1 && Step_2) - - // ------- BOTH CARDINAL DIRECTIONS OF THE DIAGONAL EXIST IN THE GAME WORLD ------- - - var/check_1 = 0 - var/check_2 = 0 - if(step_to(D, Step_1)) - check_1 = 1 - for(var/obj/border_obstacle in Step_1) - if(border_obstacle.flags & ON_BORDER) - if(!border_obstacle.CheckExit(D, src)) - check_1 = 0 - // ------- YOU TRIED TO CLICK ON AN ITEM THROUGH A WINDOW (OR SIMILAR THING THAT LIMITS ON BORDERS) ON ONE OF THE DIRECITON TILES ------- - for(var/obj/border_obstacle in get_turf(src)) - if((border_obstacle.flags & ON_BORDER) && (src != border_obstacle)) - if(!border_obstacle.CanPass(D, D.loc, 1, 0)) - // ------- YOU TRIED TO CLICK ON AN ITEM THROUGH A WINDOW (OR SIMILAR THING THAT LIMITS ON BORDERS) ON THE TILE YOU'RE ON ------- - check_1 = 0 - - D.loc = usr.loc - if(step_to(D, Step_2)) - check_2 = 1 - - for(var/obj/border_obstacle in Step_2) - if(border_obstacle.flags & ON_BORDER) - if(!border_obstacle.CheckExit(D, src)) - check_2 = 0 - for(var/obj/border_obstacle in get_turf(src)) - if((border_obstacle.flags & ON_BORDER) && (src != border_obstacle)) - if(!border_obstacle.CanPass(D, D.loc, 1, 0)) - check_2 = 0 - - - if(check_1 || check_2) - ok = 1 - // ------- YOU CAN REACH THE ITEM THROUGH AT LEAST ONE OF THE TWO DIRECTIONS. GOOD. ------- - - /* - More info: - If you're trying to click an item in the north-east of your mob, the above section of code will first check if tehre's a tile to the north or you and to the east of you - These two tiles are Step_1 and Step_2. After this, a new dummy object is created on your location. It then tries to move to Step_1, If it succeeds, objects on the turf you're on and - the turf that Step_1 is are checked for items which have the ON_BORDER flag set. These are itmes which limit you on only one tile border. Windows, for the most part. - CheckExit() and CanPass() are use to determine this. The dummy object is then moved back to your location and it tries to move to Step_2. Same checks are performed here. - If at least one of the two checks succeeds, it means you can reach the item and ok is set to 1. - */ - else - // ------- OBJECT IS ON A CARDINAL TILE (NORTH, SOUTH, EAST OR WEST OR THE TILE YOU'RE ON) ------- - if(loc == usr.loc) - ok = 1 - // ------- OBJECT IS ON THE SAME TILE AS YOU ------- - else - ok = 1 - - //Now, check objects to block exit that are on the border - for(var/obj/border_obstacle in usr.loc) - if(border_obstacle.flags & ON_BORDER) - if(!border_obstacle.CheckExit(D, src)) - ok = 0 - - //Next, check objects to block entry that are on the border - for(var/obj/border_obstacle in get_turf(src)) - if((border_obstacle.flags & ON_BORDER) && (src != border_obstacle)) - if(!border_obstacle.CanPass(D, D.loc, 1, 0)) - ok = 0 - /* - See the previous More info, for... more info... - */ - - //del(D) - // Garbage Collect Dummy - D.loc = null - D = null - - // ------- DUMMY OBJECT'S SERVED IT'S PURPOSE, IT'S REWARDED WITH A SWIFT DELETE ------- - if(!( ok )) - // ------- TESTS ABOVE DETERMINED YOU CANNOT REACH THE TILE ------- - return 0 - - if(!( usr.restrained() || (usr.lying && usr.buckled!=src) )) - // ------- YOU ARE NOT REASTRAINED ------- - - if(W) - // ------- YOU HAVE AN ITEM IN YOUR HAND - HANDLE ATTACKBY AND AFTERATTACK ------- - var/ignoreAA = 0 //Ignore afterattack(). Surgery uses this. - if(t5) - ignoreAA = src.attackby(W, usr, params) - if(W && !ignoreAA) - W.afterattack(src, usr, (t5 ? 1 : 0), params) - - else - // ------- YOU DO NOT HAVE AN ITEM IN YOUR HAND ------- - if(istype(usr, /mob/living/carbon/human)) - // ------- YOU ARE HUMAN ------- - src.attack_hand(usr, usr.hand) - else - // ------- YOU ARE NOT HUMAN. WHAT ARE YOU - DETERMINED HERE AND PROPER ATTACK_MOBTYPE CALLED ------- - if(istype(usr, /mob/living/carbon/monkey)) - src.attack_paw(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/alien/humanoid)) - if(usr.m_intent == "walk" && istype(usr, /mob/living/carbon/alien/humanoid/hunter)) - usr.m_intent = "run" - usr.hud_used.move_intent.icon_state = "running" - usr.update_icons() - src.attack_alien(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/alien/larva)) - src.attack_larva(usr) - else if(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) - src.attack_ai(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/slime)) - src.attack_slime(usr) - else if(istype(usr, /mob/living/simple_animal)) - src.attack_animal(usr) - else - // ------- YOU ARE RESTRAINED. DETERMINE WHAT YOU ARE AND ATTACK WITH THE PROPER HAND_X PROC ------- - if(istype(usr, /mob/living/carbon/human)) - src.hand_h(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/monkey)) - src.hand_p(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/alien/humanoid)) - src.hand_al(usr, usr.hand) - else if(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) - src.hand_a(usr, usr.hand) - - else - // ------- ITEM INACESSIBLE OR CLICKING ON SCREEN ------- - if(istype(src, /obj/screen)) - // ------- IT'S THE HUD YOU'RE CLICKING ON ------- - usr.prev_move = usr.next_move - usr:lastDblClick = world.time + 2 - if(usr.next_move < world.time) - usr.next_move = world.time + 2 - else - return - - // ------- 2 DECISECOND DELAY FOR CLICKING PASSED ------- - - if(!( usr.restrained() )) - - // ------- YOU ARE NOT RESTRAINED ------- - if((W && !( istype(src, /obj/screen) ))) - // ------- IT SHOULD NEVER GET TO HERE, DUE TO THE ISTYPE(SRC, /OBJ/SCREEN) FROM PREVIOUS IF-S - I TESTED IT WITH A DEBUG OUTPUT AND I COULDN'T GET THIST TO SHOW UP. ------- - src.attackby(W, usr, params) - if(W) - W.afterattack(src, usr,, params) - else - // ------- YOU ARE NOT RESTRAINED, AND ARE CLICKING A HUD OBJECT ------- - if(istype(usr, /mob/living/carbon/human)) - src.attack_hand(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/monkey)) - src.attack_paw(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/alien/humanoid)) - src.attack_alien(usr, usr.hand) - else - // ------- YOU ARE RESTRAINED CLICKING ON A HUD OBJECT ------- - if(istype(usr, /mob/living/carbon/human)) - src.hand_h(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/monkey)) - src.hand_p(usr, usr.hand) - else if(istype(usr, /mob/living/carbon/alien/humanoid)) - src.hand_al(usr, usr.hand) - else - // ------- YOU ARE CLICKING ON AN OBJECT THAT'S INACCESSIBLE TO YOU AND IS NOT YOUR HUD ------- - if((LASER in usr:mutations) && usr:a_intent == I_HARM && world.time >= usr.next_move) - // ------- YOU HAVE THE LASER MUTATION, YOUR INTENT SET TO HURT AND IT'S BEEN MORE THAN A DECISECOND SINCE YOU LAS TATTACKED ------- - - var/turf/T = get_turf(usr) - var/turf/U = get_turf(src) - - - if(istype(usr, /mob/living/carbon/human)) - usr:nutrition -= rand(1,5) - usr:handle_regular_hud_updates() - - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( usr.loc ) - A.icon = 'icons/effects/genetics.dmi' - A.icon_state = "eyelasers" - playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) - - A.firer = usr - A.def_zone = usr:get_organ_target() - A.original = src - A.current = T - A.yo = U.y - T.y - A.xo = U.x - T.x - A.fire() - - usr.next_move = world.time + 6 - return diff --git a/code/controllers/ProcessScheduler/core/process.dm b/code/controllers/ProcessScheduler/core/process.dm index acf34e3c4c8..24fde08e2d8 100644 --- a/code/controllers/ProcessScheduler/core/process.dm +++ b/code/controllers/ProcessScheduler/core/process.dm @@ -105,6 +105,10 @@ last_task = 0 last_object = null +/datum/controller/process/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + /datum/controller/process/proc/started() // Initialize run_start so we can detect hung processes. run_start = TimeOfGame @@ -180,8 +184,7 @@ // Allow inheritors to clean up if needed onKill() - // This should del - del(src) + qdel(src) // Do not call this directly - use SHECK or SCHECK_EVERY /datum/controller/process/proc/sleepCheck(var/tickId = 0) diff --git a/code/controllers/ProcessScheduler/core/processScheduler.dm b/code/controllers/ProcessScheduler/core/processScheduler.dm index 494e776650d..8eb0b37c0b8 100644 --- a/code/controllers/ProcessScheduler/core/processScheduler.dm +++ b/code/controllers/ProcessScheduler/core/processScheduler.dm @@ -58,6 +58,10 @@ var/global/datum/controller/processScheduler/processScheduler timeAllowance = world.tick_lag * 0.5 timeAllowanceMax = world.tick_lag +/datum/controller/processScheduler/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + /** * deferSetupFor * @param path processPath @@ -72,7 +76,7 @@ var/global/datum/controller/processScheduler/processScheduler /datum/controller/processScheduler/proc/setup() // There can be only one if(processScheduler && (processScheduler != src)) - del(src) + qdel(src) return 0 var/process diff --git a/code/controllers/Processes/fires.dm b/code/controllers/Processes/fires.dm new file mode 100644 index 00000000000..4566143a906 --- /dev/null +++ b/code/controllers/Processes/fires.dm @@ -0,0 +1,23 @@ +var/global/datum/controller/process/fire/fire_master + +/datum/controller/process/fire + var/list/burning = list() + +/datum/controller/process/fire/setup() + name = "fire" + schedule_interval = 20 //every 2 seconds + fire_master = src + log_startup_progress("Fire process starting up.") + +/datum/controller/process/fire/statProcess() + ..() + stat(null, "[burning.len] burning objects") + +/datum/controller/process/fire/doWork() + for(var/obj/burningobj in burning) + if(burningobj.burn_state == ON_FIRE) + if(burningobj.burn_world_time < world.time) + burningobj.burn() + SCHECK + else + burning.Remove(burningobj) \ No newline at end of file diff --git a/code/controllers/Processes/shuttles.dm b/code/controllers/Processes/shuttles.dm index 90b187017ac..25aa56d553d 100644 --- a/code/controllers/Processes/shuttles.dm +++ b/code/controllers/Processes/shuttles.dm @@ -183,6 +183,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 continue var/turf/T = get_turf(thing) + // TODO: Tie into space manager if(T && T.z == ZLEVEL_STATION) callShuttle = 0 break @@ -229,6 +230,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 if(!M.roundstart_move) continue for(var/obj/docking_port/stationary/S in stationary) + // TODO: Tie into space manager if(S.z != ZLEVEL_STATION && findtext(S.id, M.id)) S.width = M.width S.height = M.height diff --git a/code/controllers/Processes/weather.dm b/code/controllers/Processes/weather.dm index 999c6c51dc5..df9ee95369b 100644 --- a/code/controllers/Processes/weather.dm +++ b/code/controllers/Processes/weather.dm @@ -1,3 +1,4 @@ +// TODO: Tie into space manager //Used for all kinds of weather, ex. lavaland ash storms. var/global/datum/controller/process/weather/weather_master diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 5cedd40abfc..09596d4445c 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -61,6 +61,7 @@ var/ToRban = 0 var/automute_on = 0 //enables automuting/spam prevention var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access. + var/round_abandon_penalty_period = 30 MINUTES // Time from round start during which ghosting out is penalized var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors @@ -560,6 +561,9 @@ if("max_loadout_points") config.max_loadout_points = text2num(value) + if("round_abandon_penalty_period") + config.round_abandon_penalty_period = MinutesToTicks(text2num(value)) + else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index c3c0ea77ddb..ed618d7d72f 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -24,7 +24,7 @@ var/global/pipe_processing_killed = 0 //There can be only one master_controller. Out with the old and in with the new. if(master_controller != src) if(istype(master_controller)) - del(master_controller) + qdel(master_controller) master_controller = src var/watch=0 @@ -38,16 +38,32 @@ var/global/pipe_processing_killed = 0 if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase() if(!syndicate_code_response) syndicate_code_response = generate_code_phrase() +/datum/controller/game_controller/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + /datum/controller/game_controller/proc/setup() world.tick_lag = config.Ticklag - zlevels.initialize() - preloadTemplates() if(!config.disable_away_missions) createRandomZlevel() + // Create 6 extra space levels to put space ruins on if(!config.disable_space_ruins) - seedRuins(7, rand(0, 3), /area/space, space_ruins_templates) + var/timer = start_watch() + log_startup_progress("Creating random space levels...") + seedRuins(ZLEVEL_EMPTY, rand(0, 3), /area/space, space_ruins_templates) + log_startup_progress("Loaded random space levels in [stop_watch(timer)]s.") + + // We'll keep this around for the time when we finally expunge all + // code that checks on hard-defined z positions + + // var/num_extra_space = 6 + // for(var/i = 1, i <= num_extra_space, i++) + // var/zlev = space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED) + // seedRuins(zlev, rand(0, 3), /area/space, space_ruins_templates) + + space_manager.do_transition_setup() setup_objects() setupgenetics() diff --git a/code/datums/action.dm b/code/datums/action.dm index 2f7e6296f80..8457a7fc825 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -173,6 +173,9 @@ /datum/action/item_action/toggle_mister name = "Toggle Mister" +/datum/action/item_action/toggle_headphones + name = "Toggle Headphones" + /datum/action/item_action/toggle_helmet_light name = "Toggle Helmet Light" diff --git a/code/datums/cache/air_alarm.dm b/code/datums/cache/air_alarm.dm index 83b2e8246e5..67de7f95f21 100644 --- a/code/datums/cache/air_alarm.dm +++ b/code/datums/cache/air_alarm.dm @@ -2,7 +2,7 @@ var/global/datum/repository/air_alarm/air_alarm_repository = new() /datum/repository/air_alarm/proc/air_alarm_data(var/list/monitored_alarms, var/refresh = 0, var/obj/machinery/alarm/passed_alarm) var/alarms[0] - + var/datum/cache_entry/cache_entry = cache_data if(!cache_entry) cache_entry = new/datum/cache_entry @@ -15,13 +15,14 @@ var/global/datum/repository/air_alarm/air_alarm_repository = new() alarms[++alarms.len] = passed_alarm.get_nano_data_console() else for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : air_alarms)) + // TODO: Tie into space manager if(!monitored_alarms && alarm.z != ZLEVEL_STATION && alarm.z != ZLEVEL_ASTEROID) continue alarms[++alarms.len] = alarm.get_nano_data_console() - + cache_entry.timestamp = world.time //+ 10 SECONDS - cache_entry.data = alarms + cache_entry.data = alarms return alarms /datum/repository/air_alarm/proc/update_cache(var/obj/machinery/alarm/alarm) - return air_alarm_data(refresh = 1, passed_alarm = alarm) \ No newline at end of file + return air_alarm_data(refresh = 1, passed_alarm = alarm) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 586cf8af512..0a71929d155 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -161,7 +161,7 @@ body += "
" if(sprite) - body += "
[bicon(D)]" + body += "
[bicon(D, use_class=0)]" else body += "
" @@ -350,14 +350,14 @@ body else if(isicon(value)) #ifdef VARSICON - html += "[name] = /icon ([value]) [bicon(value)]" + html += "[name] = /icon ([value]) [bicon(value, use_class=0)]" #else html += "[name] = /icon ([value])" #endif else if(istype(value, /image)) #ifdef VARSICON - html += "[name] \ref[value] = /image ([value]) [bicon(value)]" + html += "[name] \ref[value] = /image ([value]) [bicon(value, use_class=0)]" #else html += "[name] \ref[value] = /image ([value])" #endif diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 4bef4896cc8..b97ce1f5c7f 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -406,7 +406,8 @@ var/list/advance_cures = list( AD.Refresh() for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) - if(H.z != 1) + // TODO: Tie into space manager + if(H.z != ZLEVEL_STATION) continue if(!H.HasDisease(D)) H.ForceContractDisease(D) diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index 83b3a4a226a..172c4b63757 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -43,11 +43,11 @@ Bonus return /datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A) - var/get_damage = (sqrt(20+A.totalStageSpeed())/2)+(sqrt(16+A.totalStealth())*1) + var/get_damage = sqrt(21+A.totalStageSpeed()*0.5)+sqrt(16+A.totalStealth()) M.adjustOxyLoss(get_damage) return 1 /datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A) - var/get_damage = (sqrt(20+A.totalStageSpeed())/2)+(sqrt(16+A.totalStealth()*5)) + var/get_damage = sqrt(21+A.totalStageSpeed()*0.5)+sqrt(16+A.totalStealth()*5) M.adjustOxyLoss(get_damage) return 1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm index eb7afcaf6be..cba4d4a4cd0 100644 --- a/code/datums/diseases/advance/symptoms/damage_converter.dm +++ b/code/datums/diseases/advance/symptoms/damage_converter.dm @@ -45,9 +45,11 @@ Bonus if(!parts.len) return - M.heal_overall_damage(get_damage, get_damage) + for(var/obj/item/organ/external/E in parts) + E.heal_damage(get_damage, get_damage, 0, 0) M.adjustToxLoss(get_damage*parts.len) + else if(M.getFireLoss() > 0 || M.getBruteLoss() > 0) M.adjustFireLoss(-get_damage) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 3ec0f16358a..9234b54b088 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -21,7 +21,7 @@ Bonus resistance = -4 stage_speed = -4 transmittable = -3 - level = 6 + level = 5 severity = 0 /datum/symptom/sensory_restoration/Activate(var/datum/disease/advance/A) @@ -38,12 +38,12 @@ Bonus M.reagents.add_reagent_list(list("antihol"=10, "oculine"=10)) to_chat(M, "You feel sober.") if(4) - if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 && M.reagents.get_reagent_amount("synaptizine") < 10) - M.reagents.add_reagent_list(list("antihol"=10, "oculine"=10, "synaptizine"=5)) + if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 && M.reagents.get_reagent_amount("synaphydramine") < 10) + M.reagents.add_reagent_list(list("antihol"=10, "oculine"=10, "synaphydramine"=5)) to_chat(M, "You feel focused.") if(5) - if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 && M.reagents.get_reagent_amount("synaptizine") < 10 && M.reagents.get_reagent_amount("mannitol") < 10) - M.reagents.add_reagent_list(list("mannitol"=10, "antihol"=10, "oculine"=10, "synaptizine"=10)) + if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 && M.reagents.get_reagent_amount("synaphydramine") < 10 && M.reagents.get_reagent_amount("mannitol") < 10) + M.reagents.add_reagent_list(list("mannitol"=10, "antihol"=10, "oculine"=10, "synaphydramine"=10)) to_chat(M, "Your mind feels relaxed.") return diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 8b26807199e..a2d00e69558 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -48,7 +48,7 @@ // This system will metaphorically snap in half (not postpone init everywhere) // if given a multi-z template // it might need to be adapted for that when that time comes - zlevels.add_dirt(placement.z) + space_manager.add_dirt(placement.z) var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1) if(!bounds) return 0 @@ -65,7 +65,7 @@ late_setup_level( block(bot_left, top_right), block(ST_bot_left, ST_top_right)) - zlevels.remove_dirt(placement.z) + space_manager.remove_dirt(placement.z) log_game("[name] loaded at [min_x],[min_y],[placement.z]") return 1 diff --git a/code/datums/spell.dm b/code/datums/spell.dm index c7aa3dfd9a0..63b9405f73e 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -67,6 +67,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin caster.reset_view(0) return 0 + // TODO: Tie into space manager if(user.z == ZLEVEL_CENTCOMM && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel return 0 if(user.z == ZLEVEL_CENTCOMM && ticker.mode.name == "ragin' mages") @@ -363,6 +364,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list)) return 0 + // TODO: Tie into space manager if(user.z == ZLEVEL_CENTCOMM && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel return 0 if(user.z == ZLEVEL_CENTCOMM && ticker.mode.name == "ragin' mages") @@ -400,4 +402,4 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin return 0 if(isbrain(user) || ispAI(user)) return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index eba2aa895f4..b75cba1f858 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -98,6 +98,7 @@ var/canmove = 1 density = 0 anchored = 1 + burn_state = LAVA_PROOF /obj/effect/dummy/spell_jaunt/Destroy() // Eject contents if deleted somehow diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index d39ff42ea51..3d2ab9d4718 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -12,7 +12,6 @@ range = 7 cooldown_min = 30 //30 deciseconds reduction per rank selection_type = "range" - var/list/compatible_mobs = list(/mob/living/carbon/human) action_icon_state = "barn" @@ -26,7 +25,8 @@ if(!target) return - if((target.type in compatible_mobs) || ishuman(target)) + + if(!ishuman(target)) to_chat(user, "It'd be stupid to curse [target] with a horse's head!") return diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index cafbb579f34..211374c3c31 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -309,6 +309,14 @@ var/list/uplink_items = list() item = /obj/item/clothing/under/contortionist cost = 6 job = list("Life Support Specialist") + +/datum/uplink_item/dangerous/energizedfireaxe + name = "Energized Fire Axe" + desc = "A fire axe with a massive electrical charge built into it. It can release this charge on its first victim and will be rather plain after that." + reference = "EFA" + item = /obj/item/weapon/twohanded/energizedfireaxe + cost = 10 + job = list("Life Support Specialist") //Stimulants @@ -462,6 +470,13 @@ var/list/uplink_items = list() gamemodes = list(/datum/game_mode/nuclear) surplus = 0 +/datum/uplink_item/dangerous/atmosgrenades + name = "Atmos Grenades" + desc = "A box of two (2) grenades that wreak havoc with the atmosphere of the target area. Capable of engulfing a large area in lit plasma, or N2O. Deploy with extreme caution!" + reference = "AGG" + item = /obj/item/weapon/storage/box/syndie_kit/atmosgasgrenades + cost = 6 + /datum/uplink_item/dangerous/emp name = "EMP Grenades and Implanter Kit" desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \ @@ -879,8 +894,8 @@ var/list/uplink_items = list() cost = 1 /datum/uplink_item/device_tools/surgerybag - name = "Syndicate Surgery Dufflebag" - desc = "The Syndicate surgery dufflebag is a toolkit containing all surgery tools, a straitjacket, and a muzzle." + name = "Syndicate Surgery Duffelbag" + desc = "The Syndicate surgery duffelbag is a toolkit containing all surgery tools, a straitjacket, and a muzzle." reference = "SSDB" item = /obj/item/weapon/storage/backpack/duffel/syndie/surgery cost = 4 diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm index 07735e85968..bf942b7ceba 100644 --- a/code/datums/weather/weather_types.dm +++ b/code/datums/weather/weather_types.dm @@ -1,4 +1,5 @@ //Different types of weather. +// TODO: Tie into space manager /datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object. name = "the floor is lava" diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm index b13cfe9ca05..b78345b0638 100644 --- a/code/defines/procs/radio.dm +++ b/code/defines/procs/radio.dm @@ -47,6 +47,7 @@ /proc/get_receiver_reception(var/receiver, var/datum/signal/signal) if(receiver && check_signal(signal)) var/turf/pos = get_turf(receiver) + // Maybe should get tie-in to the space manager? if(pos && (pos.z in signal.data["level"])) return TELECOMMS_RECEPTION_RECEIVER return TELECOMMS_RECEPTION_NONE diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 3992f97fd0b..07ad5956002 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -67,6 +67,7 @@ var/list/teleportlocs = list() if(AR.no_teleportlocs) continue if(teleportlocs.Find(AR.name)) continue var/turf/picked = safepick(get_area_turfs(AR.type)) + // TODO: Tie into space manager if(picked && (picked.z == ZLEVEL_STATION)) teleportlocs += AR.name teleportlocs[AR.name] = AR @@ -2632,4 +2633,3 @@ var/list/the_station_areas = list ( /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai, ) - diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 43540f347de..5963d461daf 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -376,6 +376,7 @@ return 1 else // There's a gravity generator on our z level + // This would do well when integrated with the z level manager if(T && gravity_generators["[T.z]"] && length(gravity_generators["[T.z]"])) return 1 return 0 diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 229bc979c37..89b31f478dd 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -72,7 +72,7 @@ var/global/max_secret_rooms = 6 treasureitems = list(/obj/item/device/soulstone=1, /obj/item/clothing/suit/space/cult=1, /obj/item/weapon/bedsheet/cult=2, /obj/item/clothing/suit/hooded/cultrobes=2, /mob/living/simple_animal/hostile/creature=3) fluffitems = list(/obj/effect/gateway=1,/obj/effect/gibspawner=1,/obj/structure/cult/talisman=1,/obj/item/toy/crayon/red=2, - /obj/item/organ/internal/heart=2, /obj/effect/decal/cleanable/blood=4,/obj/structure/table/woodentable=2,/obj/item/weapon/ectoplasm=3, + /obj/item/organ/internal/heart=2, /obj/effect/decal/cleanable/blood=4,/obj/structure/table/woodentable=2,/obj/item/weapon/reagent_containers/food/snacks/ectoplasm=3, /obj/item/clothing/head/helmet/space/cult=1, /obj/item/clothing/shoes/cult=1) if("wizden") diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 7e5c26b52e5..0435ead41b2 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -13,6 +13,7 @@ var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. var/simulated = 1 //filter for actions - used by lighting overlays var/atom_say_verb = "says" + var/dont_save = 0 // For atoms that are temporary by necessity - like lighting overlays ///Chemistry. var/datum/reagents/reagents = null @@ -41,6 +42,7 @@ if(!T) return 0 + // TODO: Tie into space manager if(T.z != ZLEVEL_CENTCOMM)//if not, don't bother return 0 @@ -58,6 +60,7 @@ if(!T) return 0 + // TODO: Tie into space manager if(T.z != ZLEVEL_CENTCOMM)//if not, don't bother return 0 @@ -446,11 +449,10 @@ /atom/proc/narsie_act() return -/atom/proc/atom_say(var/message) - if((!message)) +/atom/proc/atom_say(message) + if(!message) return - for(var/mob/O in hearers(src, null)) - O.show_message("[src] [atom_say_verb], \"[message]\"",2) + audible_message("[src] [atom_say_verb], \"[message]\"") /atom/proc/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list()) return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index cb612eec455..a903e4ea8ed 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -44,8 +44,8 @@ // at which point object creations are a fair toss more seldom /atom/movable/proc/attempt_init() var/turf/T = get_turf(src) - if(T && zlevels.is_zlevel_dirty(T.z)) - zlevels.postpone_init(T.z, src) + if(T && space_manager.is_zlevel_dirty(T.z)) + space_manager.postpone_init(T.z, src) else if(auto_init) initialize() diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 76254b13c44..4224ad1aa5e 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -419,3 +419,26 @@ var/global/list/bad_blocks[0] unique_enzymes = md5(character.real_name) reg_dna[unique_enzymes] = character.real_name + +// Hmm, I wonder how to go about this without a huge convention break +/datum/dna/serialize() + var/data = list() + data["UE"] = unique_enzymes + data["SE"] = SE.Copy() // This is probably too lazy for my own good + data["UI"] = UI.Copy() + data["species"] = species // This works because `species` is a string, not a datum + // Because old DNA coders were insane or something + data["b_type"] = b_type + data["real_name"] = real_name + return data + +/datum/dna/deserialize(data) + unique_enzymes = data["UE"] + // The de-serializer is unlikely to tamper with the lists + SE = data["SE"] + UI = data["UI"] + UpdateUI() + UpdateSE() + species = data["species"] + b_type = data["b_type"] + real_name = data["real_name"] diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm index cac55d7d317..f2489a2490a 100644 --- a/code/game/dna/genes/goon_disabilities.dm +++ b/code/game/dna/genes/goon_disabilities.dm @@ -131,7 +131,17 @@ /datum/dna/gene/disability/speech/swedish/OnSay(var/mob/M, var/message) // svedish - message = replacetext(message,"w","v") + message = replacetextEx(message,"W","V") + message = replacetextEx(message,"w","v") + message = replacetextEx(message,"J","Y") + message = replacetextEx(message,"j","y") + message = replacetextEx(message,"A",pick("Å","Ä","Æ","A")) + message = replacetextEx(message,"a",pick("å","ä","æ","a")) + message = replacetextEx(message,"BO","BJO") + message = replacetextEx(message,"Bo","Bjo") + message = replacetextEx(message,"bo","bjo") + message = replacetextEx(message,"O",pick("Ö","Ø","O")) + message = replacetextEx(message,"o",pick("ö","ø","o")) if(prob(30)) message += " Bork[pick("",", bork",", bork, bork")]!" return message diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 1dc7985d648..7d9aed3d442 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -80,6 +80,7 @@ var/mob/living/demon_type = /mob/living/simple_animal/slaughter /obj/item/weapon/antag_spawner/slaughter_demon/attack_self(mob/user as mob) + // TODO: Tie into space manager if(user.z == ZLEVEL_CENTCOMM)//this is to make sure the wizard does NOT summon a demon from the Den.. to_chat(user, "You should probably wait until you reach the station.") return @@ -135,4 +136,4 @@ veil_msg = "You sense an adorable presence \ lurking just beyond the veil..." objective_verb = "Hug and Tickle" - demon_type = /mob/living/simple_animal/slaughter/laughter \ No newline at end of file + demon_type = /mob/living/simple_animal/slaughter/laughter diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 35b469258ef..ebab12dc0f2 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -118,6 +118,7 @@ var/list/blob_nodes = list() if(directory[ckey(blob.key)]) blob_client = directory[ckey(blob.key)] location = get_turf(C) + // TODO: Tie into space manager if(location.z != ZLEVEL_STATION || istype(location, /turf/space)) if(!warned) to_chat(C, "You feel ready to burst, but this isn't an appropriate place! You must return to the station!") diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index c6d3bd13e0f..e74a0677942 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -23,6 +23,7 @@ var/nukecode = rand(10000, 99999) for(var/obj/machinery/nuclearbomb/bomb in world) if(bomb && bomb.r_code) + // TODO: Tie into space manager if(bomb.z == ZLEVEL_STATION) bomb.r_code = nukecode diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index e2f4fc50c12..5b0884788b9 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -36,7 +36,6 @@ melee_damage_upper = 4 attacktext = "hits" attack_sound = 'sound/weapons/genhit1.ogg' - del_on_death = 1 speak_emote = list("pulses") var/obj/effect/blob/factory/factory = null var/list/human_overlays = list() @@ -92,6 +91,7 @@ loc.visible_message("The corpse of [H.name] suddenly rises!") /mob/living/simple_animal/hostile/blob/blobspore/death(gibbed) + ..() // On death, create a small smoke of harmful gas (s-Acid) var/datum/effect/system/chem_smoke_spread/S = new var/turf/location = get_turf(src) @@ -108,7 +108,7 @@ S.attach(location) S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud S.start() - ..() + qdel(src) /mob/living/simple_animal/hostile/blob/blobspore/Destroy() if(factory) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 01e44ba5888..5640c9a71f6 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -110,7 +110,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" if(identity_theft.target && identity_theft.target.current) identity_theft.target_real_name = kill_objective.target.current.real_name //Whoops, forgot this. var/mob/living/carbon/human/H = identity_theft.target.current - if(H.species && H.species.flags && H.species.flags & NO_SCAN) // For species that can't be absorbed - should default to an escape objective instead + if(check_species_absorb(H.species)) // For species that can't be absorbed - should default to an escape objective return else identity_theft.explanation_text = "Escape on the shuttle or an escape pod with the identity of [identity_theft.target_real_name], the [identity_theft.target.assigned_role] while wearing their identification card." @@ -329,3 +329,5 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" return 1 +/proc/check_species_absorb(datum/species/S) + return !((S.flags & NO_DNA) || (S.flags & NO_SCAN) || (S.flags & NO_BLOOD)) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 7ad1e33b747..dc12c64fbed 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -14,7 +14,8 @@ var/list/sacrificed = list() for(var/obj/effect/rune/R in world) if(R == src) continue - if(R.word1 == cultwords["travel"] && R.word2 == cultwords["self"] && R.word3 == key && R.z != 2) + // TODO: Tie into space manager + if(R.word1 == cultwords["travel"] && R.word2 == cultwords["self"] && R.word3 == key && R.z != ZLEVEL_CENTCOMM) index++ allrunesloc.len = index allrunesloc[index] = R.loc diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index fd384e61d1f..54db8374d29 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -2,6 +2,7 @@ //command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines) + // TODO: Tie into space manager if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded) if(temp_vent.parent.other_atmosmch.len > 50) // Stops Aliens getting stuck in small networks. See: Security, Virology vents += temp_vent @@ -53,7 +54,7 @@ apc.overload_lighting() else - for(var/obj/machinery/power/apc/apc in machines) + for(var/obj/machinery/power/apc/apc in apcs) apc.overload_lighting() return diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e91f7156208..a3125ed1895 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -427,6 +427,7 @@ proc/get_nt_opposed() /proc/get_nuke_code() var/nukecode = "ERROR" for(var/obj/machinery/nuclearbomb/bomb in world) + // TODO: Tie into space manager if(bomb && bomb.r_code && bomb.z == ZLEVEL_STATION) nukecode = bomb.r_code return nukecode @@ -452,6 +453,7 @@ proc/get_nt_opposed() else text += " survived" if(fleecheck && ply.current.z > ZLEVEL_STATION) + // TODO: Tie into space manager text += " while fleeing the station" if(ply.current.real_name != ply.name) text += " as [ply.current.real_name]" @@ -468,4 +470,4 @@ proc/get_nt_opposed() else text += "
Objective #[count]: [objective.explanation_text] Fail." count++ - return text \ No newline at end of file + return text diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 7d6ea9b4e7d..4fd8c5a452b 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -266,7 +266,8 @@ var/round_start_time = 0 M.client.screen += cinematic if(M.stat != DEAD) var/turf/T = get_turf(M) - if(T && T.z == 1) + // TODO: Tie into space manager + if(T && T.z == ZLEVEL_STATION) M.death(0) //no mercy //Now animate the cinematic diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index c6b65472c2e..59a731bed47 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -1,19 +1,3 @@ -// TO DO: -/* -epilepsy flash on lights -delay round message -microwave makes robots -dampen radios -reactivate cameras - done -eject engine -core sheild -cable stun -rcd light flash thingy on matter drain - - - -*/ - /datum/AI_Module var/uses = 0 var/module_name @@ -25,7 +9,6 @@ rcd light flash thingy on matter drain var/power_type - /datum/AI_Module/large/ uses = 1 @@ -33,28 +16,11 @@ rcd light flash thingy on matter drain uses = 5 -/datum/AI_Module/large/fireproof_core - module_name = "Core Upgrade" - mod_pick_name = "coreup" - description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." - cost = 50 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/fireproof_core - -/mob/living/silicon/ai/proc/fireproof_core() - set category = "Malfunction" - set name = "Fireproof Core" - for(var/mob/living/silicon/ai/ai in player_list) - ai.fire_res_on_core = 1 - src.verbs -= /mob/living/silicon/ai/proc/fireproof_core - to_chat(src, "Core fireproofed.") - /datum/AI_Module/large/upgrade_turrets module_name = "AI Turret Upgrade" mod_pick_name = "turret" - description = "Improves the firing power and health of all AI turrets. This effect is permanent." - cost = 50 + description = "Improves the power and health of all AI turrets. This effect is permanent." + cost = 30 one_time = 1 power_type = /mob/living/silicon/ai/proc/upgrade_turrets @@ -69,16 +35,52 @@ rcd light flash thingy on matter drain src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets for(var/obj/machinery/porta_turret/turret in machines) var/turf/T = get_turf(turret) + // TODO: Tie into space manager if(T.z in config.station_levels) - // Increase health by 37.5% of original max, decrease delays between shots to 66% - turret.health += initial(turret.health) * 3 / 8 + turret.health += 30 turret.eprojectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR. turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' to_chat(src, "Turrets upgraded.") + + +/datum/AI_Module/large/lockdown + module_name = "Hostile Station Lockdown" + mod_pick_name = "lockdown" + description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds." + cost = 30 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/lockdown + +/mob/living/silicon/ai/proc/lockdown() + set category = "Malfunction" + set name = "Initiate Hostile Lockdown" + + if(stat) + return + + for(var/obj/machinery/door/D in airlocks) + if(D.z != ZLEVEL_STATION) + continue + spawn(0) + D.hostile_lockdown(src) + addtimer(D, "disable_lockdown", 900) + + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("alert", "lockdown") + + verbs -= /mob/living/silicon/ai/proc/lockdown + minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert") + to_chat(src, "Lockdown Initiated. Network reset in 90 seconds.") + spawn(900) + minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:") + + /datum/AI_Module/large/destroy_rcd module_name = "Destroy RCDs" mod_pick_name = "rcd" - description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Cconstruction Devices on the station." + description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station." cost = 25 one_time = 1 @@ -92,23 +94,20 @@ rcd light flash thingy on matter drain if(stat || malf_cooldown) return - for(var/obj/item/RCD in rcd_list) + for(var/obj/item/weapon/rcd/RCD in rcd_list) if(!istype(RCD, /obj/item/weapon/rcd/borg)) //Ensures that cyborg RCDs are spared. - RCD.audible_message("[RCD] begins to vibrate and buzz loudly!","[RCD] begins vibrating violently!") - spawn(50) //5 seconds to get rid of it! - if(RCD) //Make sure it still exists (In case of chain-reaction) - explosion(RCD, 0, 0, 3, 1, flame_range = 1) - qdel(RCD) + RCD.detonate_pulse() to_chat(src, "RCD detonation pulse emitted.") malf_cooldown = 1 spawn(100) malf_cooldown = 0 + /datum/AI_Module/large/mecha_domination module_name = "Viral Mech Domination" mod_pick_name = "mechjack" - description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave.\ + description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave. \ Do not allow the mech to leave the station's vicinity or allow it to be destroyed." cost = 30 one_time = 1 @@ -124,21 +123,71 @@ rcd light flash thingy on matter drain return can_dominate_mechs = 1 //Yep. This is all it does. Honk! - to_chat(src, "Virus package compiled. Select a target mech at any time. \ - You must remain on the station at all times. Loss of signal will result in total system lockout.") + to_chat(src, "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.") verbs -= /mob/living/silicon/ai/proc/mech_takeover + +/datum/AI_Module/large/break_fire_alarms + module_name = "Thermal Sensor Override" + mod_pick_name = "burnpigs" + description = "Gives you the ability to override the thermal sensors on all fire alarms. This will remove their ability to scan for fire and thus their ability to alert. \ + Anyone can check the fire alarm's interface and may be tipped off by its status." + one_time = 1 + cost = 25 + + power_type = /mob/living/silicon/ai/proc/break_fire_alarms + +/mob/living/silicon/ai/proc/break_fire_alarms() + set name = "Override Thermal Sensors" + set category = "Malfunction" + + if(stat) + return + + for(var/obj/machinery/firealarm/F in machines) + if(F.z != ZLEVEL_STATION) + continue + F.emagged = 1 + to_chat(src, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.") + verbs -= /mob/living/silicon/ai/proc/break_fire_alarms + + +/datum/AI_Module/large/break_air_alarms + module_name = "Air Alarm Safety Override" + mod_pick_name = "allow_flooding" + description = "Gives you the ability to disable safeties on all air alarms. This will allow you to use the environmental mode Flood, which disables scrubbers as well as pressure checks on vents. \ + Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality." + one_time = 1 + cost = 50 + + power_type = /mob/living/silicon/ai/proc/break_air_alarms + +/mob/living/silicon/ai/proc/break_air_alarms() + set name = "Disable Air Alarm Safeties" + set category = "Malfunction" + + if(stat) + return + + for(var/obj/machinery/alarm/AA in machines) + if(AA.z != ZLEVEL_STATION) + continue + AA.emagged = 1 + to_chat(src, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.") + verbs -= /mob/living/silicon/ai/proc/break_air_alarms + + /datum/AI_Module/small/overload_machine module_name = "Machine Overload" mod_pick_name = "overload" description = "Overloads an electrical machine, causing a small explosion. 2 uses." uses = 2 - cost = 15 + cost = 20 power_type = /mob/living/silicon/ai/proc/overload_machine -/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in world) +/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M in machines) set name = "Overload Machine" set category = "Malfunction" @@ -146,56 +195,55 @@ rcd light flash thingy on matter drain return if(istype(M, /obj/machinery)) - if(istype(M,/obj/machinery/field/generator)) - to_chat(src, "This machine can not be overloaded due to a firewall.") - return for(var/datum/AI_Module/small/overload_machine/overload in current_modules) if(overload.uses > 0) overload.uses -- - for(var/mob/V in hearers(M, null)) - V.show_message("You hear a loud electrical buzzing sound!", 2) + audible_message("You hear a loud electrical buzzing sound!") + to_chat(src, "Overloading machine circuitry...") spawn(50) - explosion(get_turf(M), 0,1,1,0) - qdel(M) + if(M) + explosion(get_turf(M), 0,1,1,0) + qdel(M) else - to_chat(src, "Out of uses.") + to_chat(src, "Out of uses.") else to_chat(src, "That's not a machine.") + /datum/AI_Module/small/override_machine module_name = "Machine Override" mod_pick_name = "override" description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses." uses = 4 - cost = 15 + cost = 30 power_type = /mob/living/silicon/ai/proc/override_machine -/mob/living/silicon/ai/proc/override_machine(obj/machinery/M as obj in world) + +/mob/living/silicon/ai/proc/override_machine(obj/machinery/M in machines) set name = "Override Machine" set category = "Malfunction" if(stat) return - if(istype(M, /obj/machinery)) - if(istype(M,/obj/machinery/field/generator)) - to_chat(src, "This machine can not be overloaded due to a firewall.") - return + if (istype(M, /obj/machinery)) + if(!M.can_be_overridden()) + to_chat(src, "Can't override this device.") for(var/datum/AI_Module/small/override_machine/override in current_modules) if(override.uses > 0) override.uses -- - for(var/mob/V in hearers(M, null)) - V.show_message("You hear a loud electrical buzzing sound!", 2) + audible_message("You hear a loud electrical buzzing sound!") to_chat(src, "Reprogramming machine behaviour...") spawn(50) - if(M) + if(M && !qdeleted(M)) new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) else - to_chat(src, "Out of uses.") + to_chat(src, "Out of uses.") else to_chat(src, "That's not a machine.") + /datum/AI_Module/large/place_cyborg_transformer module_name = "Robotic Factory (Removes Shunting)" mod_pick_name = "cyborgtransformer" @@ -267,7 +315,7 @@ rcd light flash thingy on matter drain if(success) return 1 alert(src, alert_msg) - return + /datum/AI_Module/small/blackout module_name = "Blackout" @@ -288,7 +336,7 @@ rcd light flash thingy on matter drain for(var/datum/AI_Module/small/blackout/blackout in current_modules) if(blackout.uses > 0) blackout.uses -- - for(var/obj/machinery/power/apc/apc in world) + for(var/obj/machinery/power/apc/apc in apcs) if(prob(30*apc.overload)) apc.overload_lighting() else @@ -297,6 +345,7 @@ rcd light flash thingy on matter drain else to_chat(src, "Out of uses.") + /datum/AI_Module/small/reactivate_cameras module_name = "Reactivate Camera Network" mod_pick_name = "recam" @@ -338,7 +387,8 @@ rcd light flash thingy on matter drain spawn(30) //Lag protection malf_cooldown = 0 -/datum/AI_Module/small/upgrade_cameras + +/datum/AI_Module/large/upgrade_cameras module_name = "Upgrade Camera Network" mod_pick_name = "upgradecam" description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-Proofing and light-amplified X-ray vision." //I <3 pointless technobabble @@ -357,6 +407,7 @@ rcd light flash thingy on matter drain var/upgradedcams = 0 see_override = SEE_INVISIBLE_MINIMUM //Night-vision, without which X-ray would be very limited in power. + update_sight() for(var/obj/machinery/camera/C in cameranet.cameras) if(C.assembly) @@ -378,6 +429,26 @@ rcd light flash thingy on matter drain to_chat(src, "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online.") verbs -= /mob/living/silicon/ai/proc/upgrade_cameras + +/datum/AI_Module/large/eavesdrop + module_name = "Enhanced Surveillance" + mod_pick_name = "eavesdrop" + description = "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations." + cost = 30 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/surveillance + +/mob/living/silicon/ai/proc/surveillance() + set category = "Malfunction" + set name = "Enhanced Surveillance" + + if(eyeobj) + eyeobj.relay_speech = TRUE + to_chat(src, "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") + verbs -= /mob/living/silicon/ai/proc/surveillance + + /datum/module_picker var/temp = null var/processing_time = 100 @@ -420,6 +491,10 @@ rcd light flash thingy on matter drain return var/mob/living/silicon/ai/A = usr + if(A.stat == DEAD) + to_chat(A, "You are already dead!") //Omae Wa Mou Shindeiru + return + for(var/datum/AI_Module/AM in possible_modules) if(href_list[AM.mod_pick_name]) @@ -441,6 +516,7 @@ rcd light flash thingy on matter drain break // Give the power and take away the money. + A.view_core() //A BYOND bug requires you to be viewing your core before your verbs update A.verbs += AM.power_type A.current_modules += new AM.type temp = AM.description @@ -449,6 +525,4 @@ rcd light flash thingy on matter drain if(href_list["showdesc"]) if(AM.mod_pick_name == href_list["showdesc"]) temp = AM.description - - src.use(usr) - return + use(usr) \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 77c45956eb4..fb85a0a1606 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -141,6 +141,7 @@ /datum/game_mode/proc/check_ai_loc() for(var/datum/mind/AI_mind in malf_ai) var/turf/ai_location = get_turf(AI_mind.current) + // TODO: Tie into space manager if(ai_location && (ai_location.z == ZLEVEL_STATION)) return 1 return 0 @@ -343,4 +344,4 @@ text += module_text_temp to_chat(world, text) - return 1 \ No newline at end of file + return 1 diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 2f7af290229..a2ff0f4e1d8 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -36,7 +36,8 @@ var/Me = pickweight(meteortypes) var/obj/effect/meteor/M = new Me(pickedstart) M.dest = pickedgoal - M.z_original = 1 + // TODO: Tie into space manager + M.z_original = ZLEVEL_STATION spawn(0) walk_towards(M, M.dest, 1) return @@ -102,6 +103,7 @@ var/dropamt = 2 /obj/effect/meteor/Move() + // TODO: Tie into space manager if(z != z_original || loc == dest) qdel(src) return @@ -309,5 +311,3 @@ /obj/effect/meteor/goreops/Bump(atom/A) A.ex_act(hitpwr) get_hit() - - diff --git a/code/game/gamemodes/miniantags/borer/borer_event.dm b/code/game/gamemodes/miniantags/borer/borer_event.dm index ed096526d10..28a0282487d 100644 --- a/code/game/gamemodes/miniantags/borer/borer_event.dm +++ b/code/game/gamemodes/miniantags/borer/borer_event.dm @@ -17,6 +17,7 @@ /datum/event/borer_infestation/start() var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + // TODO: Tie into space manager if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded) //Stops cortical borers getting stuck in small networks. See: Security, Virology if(temp_vent.parent.other_atmosmch.len > 50) @@ -33,4 +34,3 @@ spawncount-- successSpawn = 1 - diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index d5541f70e0d..ed84f211e53 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -290,6 +290,7 @@ /mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(var/mob/living/target) if(target != src) to_chat(src, "Attempting to remove this being from our presence.") + // TODO: Tie into space manager if(src.z != ZLEVEL_STATION) to_chat(src, "Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area.") return @@ -512,4 +513,3 @@ for(var/mob/M in mob_list) if(isswarmer(M) || (M in dead_mob_list)) to_chat(M, "Swarm communication - [src] states: [message]") - diff --git a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm index 5977f362bdc..73165079b6e 100644 --- a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm +++ b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm @@ -159,6 +159,7 @@ density = 0 anchored = 1 invisibility = 60 + burn_state = LAVA_PROOF /obj/effect/dummy/slaughter/relaymove(mob/user, direction) forceMove(get_step(src,direction)) diff --git a/code/game/gamemodes/mutiny/emergency_authentication_device.dm b/code/game/gamemodes/mutiny/emergency_authentication_device.dm index 168f0049560..0df97401a2e 100644 --- a/code/game/gamemodes/mutiny/emergency_authentication_device.dm +++ b/code/game/gamemodes/mutiny/emergency_authentication_device.dm @@ -49,31 +49,31 @@ return if(!mode.current_directive.directives_complete()) - state("Command aborted. Communication with CentComm is prohibited until Directive X has been completed.") + atom_say("Command aborted. Communication with CentComm is prohibited until Directive X has been completed.") return check_key_existence() if(captains_key && secondary_key) activated = 1 to_chat(user, "\blue You activate \the [src]!") - state("Command acknowledged. Initiating quantum entanglement relay to Nanotrasen High Command.") + atom_say("Command acknowledged. Initiating quantum entanglement relay to Nanotrasen High Command.") launch_shuttle() return if(!captains_key && !secondary_key) - state("Command aborted. Please present the authentication keys before proceeding.") + atom_say("Command aborted. Please present the authentication keys before proceeding.") return if(!captains_key) - state("Command aborted. Please present the Captain's Authentication Key.") + atom_say("Command aborted. Please present the Captain's Authentication Key.") return if(!secondary_key) - state("Command aborted. Please present the Emergency Secondary Authentication Key.") + atom_say("Command aborted. Please present the Emergency Secondary Authentication Key.") return // Impossible! - state("Command aborted. This unit is defective.") + atom_say("Command aborted. This unit is defective.") /obj/machinery/emergency_authentication_device/attackby(obj/item/weapon/O, mob/user, params) if(activated) @@ -81,7 +81,7 @@ return if(!mode.current_directive.directives_complete()) - state({"Command aborted. Communication with CentComm is prohibited until Directive X has been completed."}) + atom_say("Command aborted. Communication with CentComm is prohibited until Directive X has been completed.") return check_key_existence() @@ -90,9 +90,9 @@ user.drop_item() O.loc = src - state("Key received. Thank you, Captain [mode.head_loyalist].") + atom_say("Key received. Thank you, Captain [mode.head_loyalist].") spawn(5) - state(secondary_key ? "Your keys have been authenticated. Communication with CentComm is now authorized." : "Please insert the Emergency Secondary Authentication Key now.") + atom_say(secondary_key ? "Your keys have been authenticated. Communication with CentComm is now authorized." : "Please insert the Emergency Secondary Authentication Key now.") return if(istype(O, /obj/item/weapon/mutiny/auth_key/secondary) && !secondary_key) @@ -100,9 +100,9 @@ user.drop_item() O.loc = src - state("Key received. Thank you, Secondary Authenticator [mode.head_mutineer].") + atom_say("Key received. Thank you, Secondary Authenticator [mode.head_mutineer].") spawn(5) - state(captains_key ? "Your keys have been authenticated. Communication with CentComm is now authorized." : "Please insert the Captain's Authentication Key now.") + atom_say(captains_key ? "Your keys have been authenticated. Communication with CentComm is now authorized." : "Please insert the Captain's Authentication Key now.") return ..() diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm index ca867028585..5f729e4484e 100644 --- a/code/game/gamemodes/nations/nations.dm +++ b/code/game/gamemodes/nations/nations.dm @@ -142,6 +142,7 @@ datum/game_mode/nations /datum/game_mode/nations/proc/remove_access() for(var/obj/machinery/door/airlock/W in airlocks) + // TODO: Tie into space manager if(W.z in config.station_levels) W.req_access = list() @@ -253,4 +254,4 @@ datum/game_mode/nations /datum/game_mode/proc/update_nations_icons_removed(datum/mind/nations_mind) var/datum/atom_hud/antag/nations_hud = huds[GAME_HUD_NATIONS] nations_hud.leave_hud(nations_mind) - set_nations_hud(nations_mind, null) \ No newline at end of file + set_nations_hud(nations_mind, null) diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index a70074a919e..ef0edffd5f8 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -651,7 +651,7 @@ datum return 10 else return 20 - + /*burger steal_target = /obj/item/weapon/reagent_containers/food/snacks/human/burger @@ -1358,6 +1358,7 @@ datum var/turf/T = get_turf(target.current) if(target.current.stat == 2) return 1 + // TODO: Tie into space manager else if((T) && !(T.z in config.station_levels))//If they leave the station they count as dead for this return 2 else @@ -1413,4 +1414,4 @@ datum/objective/silence #undef LENIENT #undef NORMAL #undef HARD -#undef IMPOSSIBLE \ No newline at end of file +#undef IMPOSSIBLE diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm index c11b43f81ec..15a4c8ec246 100644 --- a/code/game/gamemodes/nuclear/nuclear_challenge.dm +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -19,6 +19,7 @@ if(player_list.len < MIN_CHALLENGE_PLAYERS) to_chat(user, "The enemy crew is too small to be worth declaring war on.") return + // TODO: Tie into space manager if(user.z != ZLEVEL_CENTCOMM) to_chat(user, "You have to be at your base to use this.") return diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 18791cd15f0..ae22e0ec458 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -353,6 +353,7 @@ var/bomb_set var/off_station = 0 var/turf/bomb_location = get_turf(src) + // TODO: Tie into space manager if( bomb_location && (bomb_location.z in config.station_levels) ) if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) ) off_station = 1 @@ -363,7 +364,8 @@ var/bomb_set if(ticker.mode && ticker.mode.name == "nuclear emergency") var/obj/docking_port/mobile/syndie_shuttle = shuttle_master.getShuttle("syndicate") if(syndie_shuttle) - ticker.mode:syndies_didnt_escape = (syndie_shuttle.z > 1 ? 0 : 1) //muskets will make me change this, but it will do for now + // TODO: Tie into space manager + ticker.mode:syndies_didnt_escape = (syndie_shuttle.z > ZLEVEL_STATION ? 0 : 1) //muskets will make me change this, but it will do for now ticker.mode:nuke_off_station = off_station ticker.station_explosion_cinematic(off_station,null) if(ticker.mode) @@ -401,6 +403,7 @@ var/bomb_set /obj/item/weapon/disk/nuclear/process() var/turf/disk_loc = get_turf(src) + // TODO: Tie into space manager if(disk_loc.z != ZLEVEL_STATION && disk_loc.z != ZLEVEL_CENTCOMM) var/holder = get(src, /mob) if(holder) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 825e1183529..f0a8f8957b2 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -77,7 +77,8 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ check_completion() if(target && target.current) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > 6 || !target.current.ckey) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite + // TODO: Tie into space manager + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || !target.current.ckey) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite return 1 return 0 return 1 @@ -109,6 +110,7 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey || !target.current.client) return 1 var/turf/T = get_turf(target.current) + // TODO: Tie into space manager if(T && !(T.z in config.station_levels)) //If they leave the station they count as dead for this return 2 return 0 @@ -144,6 +146,7 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ if(target in ticker.mode:head_revolutionaries) return 1 var/turf/T = get_turf(target.current) + // TODO: Tie into space manager if(T && !(T.z in config.station_levels)) //If they leave the station they count as dead for this rval = 2 return 0 @@ -170,9 +173,12 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ check_completion() if(target && target.current) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > 6 || !target.current.ckey) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite + // TODO: Tie into space manager + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || !target.current.ckey) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite return 1 - if((target.current.z in config.admin_levels)) + // TODO: Tie into space manager + var/turf/target_location = get_turf(target.current) + if(target_location.z in config.admin_levels) //No hiding in lockers and cheezing greentext. return 0 return 1 @@ -337,16 +343,6 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ /datum/objective/escape explanation_text = "Escape on the shuttle or an escape pod alive and free." - var/escape_areas = list(/area/shuttle/escape, - /area/shuttle/escape_pod1/centcom, - /area/shuttle/escape_pod1/transit, - /area/shuttle/escape_pod2/centcom, - /area/shuttle/escape_pod2/transit, - /area/shuttle/escape_pod3/centcom, - /area/shuttle/escape_pod3/transit, - /area/shuttle/escape_pod5/centcom, - /area/shuttle/escape_pod5/transit, - /area/centcom/evac) check_completion() if(issilicon(owner.current)) @@ -572,7 +568,8 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ check_completion() if(target && target.current) - if(target.current.stat == DEAD || target.current.z > 6 || !target.current.ckey) + // TODO: Tie into space manager + if(target.current.stat == DEAD || target.current.z > ZLEVEL_DERELICT || !target.current.ckey) return 1 return 0 return 1 @@ -861,4 +858,4 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ /datum/objective/wizchaos explanation_text = "Wreak havoc upon the station as much you can. Send those wandless Nanotrasen scum a message!" - completed = 1 \ No newline at end of file + completed = 1 diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index b3f889377c8..9e74459dadd 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -314,6 +314,7 @@ /datum/game_mode/revolution/proc/check_heads_victory() for(var/datum/mind/rev_mind in head_revolutionaries) var/turf/T = get_turf(rev_mind.current) + // TODO: Tie into space manager if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && rev_mind.current.client && T && (T.z == ZLEVEL_STATION)) if(ishuman(rev_mind.current)) return 0 @@ -448,4 +449,4 @@ dat += "Revolution Successful: [score_traitorswon ? "Yes" : "No"] (-[score_traitorswon * 10000] Points)
" dat += "
" - return dat \ No newline at end of file + return dat diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index e4f7bc15657..c17a4d057c7 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -128,7 +128,7 @@ datum/hSB if("hsbtoolbox") var/obj/item/weapon/storage/hsb = new/obj/item/weapon/storage/toolbox/mechanical for(var/obj/item/device/radio/T in hsb) - del(T) + qdel(T) new/obj/item/weapon/crowbar (hsb) hsb.loc = usr.loc if("hsbmedkit") diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm index 298f71bc991..a8091d04727 100644 --- a/code/game/gamemodes/scoreboard.dm +++ b/code/game/gamemodes/scoreboard.dm @@ -21,11 +21,13 @@ // Who is alive/dead, who escaped for(var/mob/living/silicon/ai/I in mob_list) + // TODO: Tie into space manager if(I.stat == DEAD && (I.z in config.station_levels)) score_deadaipenalty++ score_deadcrew++ for(var/mob/living/carbon/human/I in mob_list) + // TODO: Tie into space manager if(I.stat == DEAD && (I.z in config.station_levels)) score_deadcrew++ @@ -78,7 +80,8 @@ // Check station's power levels - for(var/obj/machinery/power/apc/A in machines) + for(var/obj/machinery/power/apc/A in apcs) + // TODO: Tie into space manager if(!(A.z in config.station_levels)) continue for(var/obj/item/weapon/stock_parts/cell/C in A.contents) @@ -88,6 +91,7 @@ // Check how much uncleaned mess is on the station for(var/obj/effect/decal/cleanable/M in world) + // TODO: Tie into space manager if(!(M.z in config.station_levels)) continue if(istype(M, /obj/effect/decal/cleanable/blood/gibs)) score_mess += 3 @@ -244,4 +248,4 @@ if(50000 to INFINITY) score_rating = "Nanotrasen's Finest" dat += "RATING: [score_rating]" - src << browse(dat, "window=roundstats;size=500x600") \ No newline at end of file + src << browse(dat, "window=roundstats;size=500x600") diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 5c509c2d26d..15ec89d71a2 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -148,102 +148,3 @@ // Populate the syndicate coalition: for(var/datum/faction/syndicate/S in ticker.factions) ticker.syndicate_coalition.Add(S) - - -/* This was used for something before, I think, but is not worth the effort to process now. -/proc/setupcorpses() - for(var/obj/effect/landmark/A in landmarks_list) - if(A.name == "Corpse") - var/mob/living/carbon/human/M = new /mob/living/carbon/human(A.loc) - M.real_name = "Corpse" - M.death() - qdel(A) - continue - if(A.name == "Corpse-Engineer") - var/mob/living/carbon/human/M = new /mob/living/carbon/human(A.loc) - M.real_name = "Corpse" - M.death() - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(M), slot_shoes) - // M.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/t_scanner(M), slot_r_store) - //M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/hardhat(M), slot_head) - else - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/welding(M), slot_head) - del(A) - continue - if(A.name == "Corpse-Engineer-Space") - var/mob/living/carbon/human/M = new /mob/living/carbon/human(A.loc) - M.real_name = "Corpse" - M.death() - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/space(M), slot_wear_suit) - // M.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/t_scanner(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/hardhat(M), slot_head) - else - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/welding(M), slot_head) - else - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space(M), slot_head) - del(A) - continue - if(A.name == "Corpse-Engineer-Chief") - var/mob/living/carbon/human/M = new /mob/living/carbon/human(A.loc) - M.real_name = "Corpse" - M.death() - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/utilitybelt(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(M), slot_shoes) - // M.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/t_scanner(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/hardhat(M), slot_head) - else - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/welding(M), slot_head) - del(A) - continue - if(A.name == "Corpse-Syndicate") - var/mob/living/carbon/human/M = new /mob/living/carbon/human(A.loc) - M.real_name = "Corpse" - M.death() - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - //M.equip_to_slot_or_del(new /obj/item/weapon/gun/revolver(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/weapon/tank/jetpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate(M), slot_wear_suit) - if(prob(50)) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(M), slot_head) - else - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate(M), slot_head) - else - M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(M), slot_head) - qdel(A) - continue -*/ diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index 9c6989cb1b9..fd3ad379fe0 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -19,9 +19,6 @@ var/list/all_items = owner.current.get_contents() for(var/obj/I in all_items) //Check for items if(istype(I, typepath) && check_special_completion(I)) - //Stealing the cheap autoinjector doesn't count - if(istype(I, /obj/item/weapon/reagent_containers/hypospray/autoinjector)) - continue return 1 return 0 @@ -111,7 +108,7 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/device/aicard/C) /datum/theft_objective/hypospray name = "a hypospray" - typepath = /obj/item/weapon/reagent_containers/hypospray + typepath = /obj/item/weapon/reagent_containers/hypospray/CMO protected_jobs = list("Chief Medical Officer") /datum/theft_objective/ablative diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 2d8018a3f8e..a0286f7c95b 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -10,7 +10,7 @@ config_tag = "vampire" restricted_jobs = list("AI", "Cyborg") protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer") - protected_species = list("Machine") + protected_species = list("Machine", "Plasmaman") required_players = 15 required_enemies = 1 recommended_enemies = 4 @@ -273,7 +273,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha owner.attack_log += text("\[[time_stamp()]\] Bit [H] ([H.ckey]) in the neck and draining their blood") H.attack_log += text("\[[time_stamp()]\] Has been bit in the neck by [owner] ([owner.ckey])") log_attack("[owner] ([owner.ckey]) bit [H] ([H.ckey]) in the neck") - owner.visible_message("[owner] bites [H]'s neck!", "You bite [H]'s neck and begin to drain their blood.", "You hear a soft puncture and a wet sucking noise.") + owner.visible_message("[owner] grabs [H]'s neck harshly and sinks in their fangs!", "You sink your fangs into [H] and begin to drain their blood.", "You hear a soft puncture and a wet sucking noise.") if(!iscarbon(owner)) H.LAssailant = null else diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index b7c1d7920e1..8b9cb6eb0e9 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -766,8 +766,8 @@ var/global/list/multiverse = list() var/obj/item/link = null var/cooldown_time = 30 //3s var/cooldown = 0 - - + burntime = 0 + burn_state = FLAMMABLE /obj/item/voodoo/attackby(obj/item/I as obj, mob/user as mob, params) if(target && cooldown < world.time) diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm index 37e9b39ce11..4d3fc5bfae8 100644 --- a/code/game/gamemodes/xenos/xenos.dm +++ b/code/game/gamemodes/xenos/xenos.dm @@ -122,6 +122,7 @@ command_announcement.Announce("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert") set_security_level("gamma") var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world + // TODO: Tie into space manager if(V && (V.z in config.station_levels)) V.locked = 0 V.update_icon() @@ -142,6 +143,7 @@ var/list/livingplayers = list() for(var/mob/M in player_list) var/turf/T = get_turf(M) + // TODO: Tie into space manager if((M) && (M.stat != 2) && M.client && T && ((T.z in config.station_levels) || shuttle_master.emergency.mode >= SHUTTLE_ESCAPE && ((T.z in config.station_levels) || (T.z in config.admin_levels)))) if(ishuman(M)) livingplayers += 1 @@ -182,4 +184,4 @@ to_chat(world, text) ..() - return 1 \ No newline at end of file + return 1 diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index fdf754df57f..b858225caf5 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -244,7 +244,7 @@ if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/under/rank/security/pod_pilot(H), slot_w_uniform) H.equip_or_collect(new /obj/item/clothing/suit/jacket/pilot(H), slot_wear_suit) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 7768cf11870..22c114a0f2c 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -39,7 +39,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) L.imp_in = H L.implanted = 1 H.sec_hud_set_implants() - captain_announcement.Announce("All hands, captain [H.real_name] on deck!") + captain_announcement.Announce("All hands, Captain [H.real_name] on deck!") callHook("captain_spawned", list("captain" = H)) return 1 @@ -143,7 +143,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) department_flag = KARMA total_positions = 1 spawn_positions = 1 - supervisors = "the nanotrasen representative" + supervisors = "the Nanotrasen representative" selection_color = "#ddddff" idtype = /obj/item/weapon/card/id/nanotrasen req_admin_notify = 1 diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 1de4ecef264..982d2be445f 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -339,7 +339,8 @@ equip(var/mob/living/carbon/human/H) - if(!H) return 0 + if(!H) + return 0 switch(H.backbag) if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) @@ -348,12 +349,10 @@ H.equip_or_collect(new /obj/item/clothing/under/suit_jacket/red(H), slot_w_uniform) H.equip_or_collect(new /obj/item/device/pda/librarian(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new /obj/item/weapon/barcodescanner(H), slot_l_hand) + H.equip_or_collect(new /obj/item/weapon/storage/bag/books(H), slot_l_hand) + H.equip_or_collect(new /obj/item/weapon/barcodescanner(H), slot_r_store) H.equip_or_collect(new /obj/item/device/laser_pointer(H), slot_l_store) - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) return 1 /datum/job/barber diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 9388942d549..24b233a4b41 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -39,6 +39,11 @@ src.colorlist += D +/obj/machinery/pdapainter/Destroy() + if(storedpda) + qdel(storedpda) + storedpda = null + return ..() /obj/machinery/pdapainter/attackby(var/obj/item/O as obj, var/mob/user as mob, params) if(istype(O, /obj/item/device/pda)) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 3ea08ee842c..4c7cd096fc3 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -710,7 +710,7 @@ data["rcon"] = rcon_setting data["target_temp"] = target_temperature - T0C data["atmos_alarm"] = alarm_area.atmosalm - data["emagged"] = emagged || isAI(user) + data["emagged"] = emagged data["modes"] = list( AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\ AALARM_MODE_VENTING = list("name"="Draught", "desc"="Siphons out air while replacing"),\ @@ -769,6 +769,7 @@ var/turf/pos = get_turf(src) data["x"] = pos.x data["y"] = pos.y + // TODO: Tie into space manager data["z"] = pos.z return data diff --git a/code/game/machinery/atmoalter/area_atmos_computer.dm b/code/game/machinery/atmoalter/area_atmos_computer.dm index 89cf4cd3610..a75c3afac88 100644 --- a/code/game/machinery/atmoalter/area_atmos_computer.dm +++ b/code/game/machinery/atmoalter/area_atmos_computer.dm @@ -113,6 +113,7 @@ scrubber.update_icon() proc/validscrubber( var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber as obj ) + // TODO: Tie into space manager if(!isobj(scrubber) || get_dist(scrubber.loc, src.loc) > src.range || scrubber.loc.z != src.loc.z) return 0 @@ -176,4 +177,4 @@ if(!found) status = "ERROR: No scrubber found!" - src.updateUsrDialog() \ No newline at end of file + src.updateUsrDialog() diff --git a/code/game/machinery/bees_apiary.dm b/code/game/machinery/bees_apiary.dm deleted file mode 100644 index ad9fb8795cb..00000000000 --- a/code/game/machinery/bees_apiary.dm +++ /dev/null @@ -1,245 +0,0 @@ -//http://www.youtube.com/watch?v=-1GadTfGFvU -//i could have done these as just an ordinary plant, but fuck it - there would have been too much snowflake code - -/obj/machinery/apiary - name = "apiary tray" - icon = 'icons/obj/hydroponics.dmi' - icon_state = "hydrotray3" - density = 1 - anchored = 1 - var/nutrilevel = 0 - var/yieldmod = 1 - var/mut = 1 - var/toxic = 0 - var/dead = 0 - var/health = -1 - var/maxhealth = 100 - var/lastcycle = 0 - var/cycledelay = 100 - var/harvestable_honey = 0 - var/beezeez = 0 - var/swarming = 0 - - var/bees_in_hive = 0 - var/list/owned_bee_swarms = list() - var/hydrotray_type = /obj/machinery/portable_atmospherics/hydroponics - -//overwrite this after it's created if the apiary needs a custom machinery sprite -/obj/machinery/apiary/New() - ..() - overlays += image('icons/obj/apiary_bees_etc.dmi', icon_state="apiary") - -/obj/machinery/apiary/bullet_act(var/obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables. - if(istype(Proj ,/obj/item/projectile/energy/floramut)) - mut++ - else if(istype(Proj ,/obj/item/projectile/energy/florayield)) - if(!yieldmod) - yieldmod += 1 -// to_chat(world, "Yield increased by 1, from 0, to a total of [myseed.yield]") - else if(prob(1/(yieldmod * yieldmod) *100))//This formula gives you diminishing returns based on yield. 100% with 1 yield, decreasing to 25%, 11%, 6, 4, 2... - yieldmod += 1 -// to_chat(world, "Yield increased by 1, to a total of [myseed.yield]") - else - ..() - return - -/obj/machinery/apiary/attackby(var/obj/item/O as obj, var/mob/user as mob, params) - if(istype(O, /obj/item/queen_bee)) - if(health > 0) - to_chat(user, "\red There is already a queen in there.") - else - health = 10 - nutrilevel += 10 - user.drop_item() - del(O) - to_chat(user, "\blue You carefully insert the queen into [src], she gets busy making a hive.") - bees_in_hive = 0 - else if(istype(O, /obj/item/beezeez)) - beezeez += 100 - nutrilevel += 10 - user.drop_item() - if(health > 0) - to_chat(user, "\blue You insert [O] into [src]. A relaxed humming appears to pick up.") - else - to_chat(user, "\blue You insert [O] into [src]. Now it just needs some bees.") - del(O) - else if(istype(O, /obj/item/weapon/minihoe)) - if(health > 0) - to_chat(user, "\red You begin to dislodge the apiary from the tray, the bees don't like that.") - angry_swarm(user) - else - to_chat(user, "\blue You begin to dislodge the dead apiary from the tray.") - if(do_after(user, 50, target = src)) - new hydrotray_type(src.loc) - new /obj/item/apiary(src.loc) - to_chat(user, "\red You dislodge the apiary from the tray.") - del(src) - else if(istype(O, /obj/item/weapon/bee_net)) - var/obj/item/weapon/bee_net/N = O - if(N.caught_bees > 0) - to_chat(user, "\blue You empty the bees into the apiary.") - bees_in_hive += N.caught_bees - N.caught_bees = 0 - else - to_chat(user, "\blue There are no more bees in the net.") - else if(istype(O, /obj/item/weapon/reagent_containers/glass)) - var/obj/item/weapon/reagent_containers/glass/G = O - if(harvestable_honey > 0) - if(health > 0) - to_chat(user, "\red You begin to harvest the honey. The bees don't seem to like it.") - angry_swarm(user) - else - to_chat(user, "\blue You begin to harvest the honey.") - if(do_after(user,50, target = src)) - G.reagents.add_reagent("honey",harvestable_honey) - harvestable_honey = 0 - to_chat(user, "\blue You successfully harvest the honey.") - else - to_chat(user, "\blue There is no honey left to harvest.") - else - angry_swarm(user) - ..() - -/obj/machinery/apiary/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - -/obj/machinery/apiary/process() - - if(swarming > 0) - swarming -= 1 - if(swarming <= 0) - for(var/mob/living/simple_animal/bee/B in src.loc) - bees_in_hive += B.strength - del(B) - else if(bees_in_hive < 10) - for(var/mob/living/simple_animal/bee/B in src.loc) - bees_in_hive += B.strength - del(B) - - if(world.time > (lastcycle + cycledelay)) - lastcycle = world.time - if(health < 0) - return - - //magical bee formula - if(beezeez > 0) - beezeez -= 1 - - nutrilevel += 2 - health += 1 - toxic = max(0, toxic - 1) - - //handle nutrients - nutrilevel -= bees_in_hive / 10 + owned_bee_swarms.len / 5 - if(nutrilevel > 0) - bees_in_hive += 1 * yieldmod - if(health < maxhealth) - health++ - else - //nutrilevel is less than 1, so we're effectively subtracting here - health += max(nutrilevel - 1, round(-health / 2)) - bees_in_hive += max(nutrilevel - 1, round(-bees_in_hive / 2)) - if(owned_bee_swarms.len) - var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms) - B.target_turf = get_turf(src) - - //clear out some toxins - if(toxic > 0) - toxic -= 1 - health -= 1 - - if(health <= 0) - return - - //make a bit of honey - if(harvestable_honey < 50) - harvestable_honey += 0.5 - - //make some new bees - if(bees_in_hive >= 10 && prob(bees_in_hive * 10)) - var/mob/living/simple_animal/bee/B = new(get_turf(src), src) - owned_bee_swarms.Add(B) - B.mut = mut - B.toxic = toxic - bees_in_hive -= 1 - - //find some plants, harvest - for(var/obj/machinery/portable_atmospherics/hydroponics/H in view(7, src)) - if(H.seed && !H.dead && prob(owned_bee_swarms.len * 10)) - src.nutrilevel++ - H.nutrilevel++ - if(mut < H.mutation_mod - 1) - mut = H.mutation_mod - 1 - else if(mut > H.mutation_mod - 1) - H.mutation_mod = mut - - //flowers give us pollen (nutrients) -/* - All plants should be giving nutrients to the hive. - if(H.myseed.type == /obj/item/seeds/harebell || H.myseed.type == /obj/item/seeds/sunflowerseed) - src.nutrilevel++ - H.nutrilevel++ -*/ - //have a few beneficial effects on nearby plants - if(prob(10)) - H.lastcycle -= 5 - if(prob(10)) - H.seed.lifespan = max(initial(H.seed.lifespan) * 1.5, H.seed.lifespan + 1) - if(prob(10)) - H.seed.endurance = max(initial(H.seed.endurance) * 1.5, H.seed.endurance + 1) - if(H.toxins && prob(10)) - H.toxins = min(0, H.toxins - 1) - toxic++ - -/obj/machinery/apiary/proc/die() - if(owned_bee_swarms.len) - var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms) - B.target_turf = get_turf(src) - B.strength -= 1 - if(B.strength <= 0) - del(B) - else if(B.strength <= 5) - B.icon_state = "bees[B.strength]" - bees_in_hive = 0 - health = 0 - -/obj/machinery/apiary/proc/angry_swarm(var/mob/M) - for(var/mob/living/simple_animal/bee/B in owned_bee_swarms) - B.feral = 25 - B.target_mob = M - - swarming = 25 - - while(bees_in_hive > 0) - var/spawn_strength = bees_in_hive - if(bees_in_hive >= 5) - spawn_strength = 6 - - var/mob/living/simple_animal/bee/B = new(get_turf(src), src) - B.target_mob = M - B.strength = spawn_strength - B.feral = 25 - B.mut = mut - B.toxic = toxic - bees_in_hive -= spawn_strength - -/obj/machinery/apiary/verb/harvest_honeycomb() - set src in oview(1) - set name = "Harvest honeycomb" - set category = "Object" - - if(usr.stat || !usr.canmove || usr.restrained()) - return - - while(health > 15) - health -= 15 - var/obj/item/weapon/reagent_containers/food/snacks/honeycomb/H = new(src.loc) - if(toxic > 0) - H.reagents.add_reagent("toxin", toxic) - - to_chat(usr, "\blue You harvest the honeycomb from the hive. There is a wild buzzing!") - angry_swarm(usr) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index aa32db20688..cccc7e52f91 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,6 +1,7 @@ /mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf) if(!T) return 1 + // TODO: Tie into space manager if((T.z in config.admin_levels)) return 1 if(T.z > MAX_Z) diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 81b2c6b86a4..a9b1e3ff31c 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -75,6 +75,7 @@ var/list/cameras = list() for(var/obj/machinery/camera/C in cameranet.cameras) + // TODO: Tie into space manager if((z > MAX_Z || C.z > MAX_Z) && (C.z != z)) //can only recieve away mission cameras on away missions continue if(!can_access_camera(C)) @@ -313,4 +314,4 @@ icon_keyboard = "power_key" icon_screen = "engie_cams" light_color = "#FAC54B" - network = list("Power Alarms","Atmosphere Alarms","Fire Alarms") \ No newline at end of file + network = list("Power Alarms","Atmosphere Alarms","Fire Alarms") diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index e87802f728c..790c516fc95 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -54,6 +54,7 @@ if(..(href, href_list)) return 1 + // TODO: Tie into space manager if((!(src.z in config.station_levels) && !(src.z in config.admin_levels))) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return 1 @@ -303,6 +304,7 @@ if(stat & (NOPOWER|BROKEN)) return + // TODO: Tie into space manager if(!(src.z in list(ZLEVEL_STATION, ZLEVEL_CENTCOMM))) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 1cb4ba64b02..d50bdbb8bc5 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -14,7 +14,6 @@ var/light_range_on = 2 var/light_power_on = 1 var/overlay_layer - atom_say_verb = "beeps" /obj/machinery/computer/New() overlay_layer = layer diff --git a/code/game/machinery/computer/honkputer.dm b/code/game/machinery/computer/honkputer.dm index 2f26663395e..75880d41975 100644 --- a/code/game/machinery/computer/honkputer.dm +++ b/code/game/machinery/computer/honkputer.dm @@ -20,6 +20,7 @@ /obj/machinery/computer/HONKputer/Topic(href, href_list) if(..()) return 1 + // TODO: Tie into space manager if(!(src.z in config.station_levels)) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return @@ -68,7 +69,8 @@ /obj/machinery/computer/HONKputer/attack_hand(var/mob/user as mob) if(..()) return - if(src.z > 6) + // TODO: Tie into space manager + if(src.z > ZLEVEL_DERELICT) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm index d50edbfd0cb..a6f1a0e6c26 100644 --- a/code/game/machinery/computer/law.dm +++ b/code/game/machinery/computer/law.dm @@ -29,7 +29,8 @@ attackby(obj/item/weapon/O as obj, mob/user as mob, params) - if(user.z > 6) + // TODO: Tie into space manager + if(user.z > ZLEVEL_DERELICT) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return if(istype(O, /obj/item/weapon/aiModule)) diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 38e6c139f2e..84b467d2072 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -43,7 +43,7 @@ loopings += ident_tag loopings[ident_tag] = 0 break - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue for(var/ident_tag in id_tags) if((M.id_tag == ident_tag) && !(ident_tag in synced) && !(ident_tag in door_only_tags)) @@ -69,7 +69,7 @@ loopings[ident_tag] = 0 break if(!(ident_tag in synced)) - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if((M.id_tag == ident_tag) && !(ident_tag in synced) && !(ident_tag in door_only_tags)) door_only_tags += ident_tag @@ -90,7 +90,7 @@ visible_message("Cannot locate any mass driver of that ID. Cancelling firing sequence!") return - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if(M.id_tag == ident_tag) spawn() @@ -104,7 +104,7 @@ M.drive() sleep(50) - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if(M.id_tag == ident_tag) spawn() @@ -242,7 +242,7 @@ maxtimes[ident_tag] = min(max(round(maxtimes[ident_tag]), 0), 120) if(href_list["door"]) var/ident_tag = href_list["driver"] - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if(M.id_tag == ident_tag) spawn() @@ -315,7 +315,7 @@ P.failchance = 0//So it has no fail chance when teleporting. spawn_marauder.Remove(P.target) - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if(M.id_tag == ident_tag) spawn() @@ -328,7 +328,7 @@ M.drive() sleep(50) - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.z != src.z) continue if(M.id_tag == ident_tag) spawn() diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index ebc0db47c32..e3683361ef2 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -65,6 +65,7 @@ health_display = "DEAD" else if(total_loss) health_display = "HURT ([total_loss])" + // TODO: Tie into space manager if((M.z in config.station_levels) && !istype(M.loc, /turf/space)) loc_display = "[get_area(M)]" dat += "ID: [T.id]
Subject: [M]
Location: [loc_display]
Health: [health_display]
" diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 7ab400823b1..c7c23dbc724 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -41,11 +41,12 @@ /obj/machinery/computer/secure_data/attack_hand(mob/user as mob) if(..()) return - if(src.z > 6) + // TODO: Tie into space manager + if(src.z > ZLEVEL_DERELICT) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return var/dat - + // search javascript var/head_content = {" @@ -89,7 +90,7 @@ //body tag start + onload and onkeypress (onkeyup) javascript event calls dat += "" - + dat += {"

"} dat += text("New Record
", src) diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 2f039841cc3..7c0680f26d3 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -40,7 +40,9 @@ /obj/machinery/computer/skills/attack_hand(mob/user as mob) if(..()) return - if(src.z > 6) + + // TODO: Tie into space manager + if(src.z > ZLEVEL_DERELICT) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return var/dat diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 257c583814b..727f4d77d8c 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -174,7 +174,9 @@ var/mob/living/occupant = null // Person waiting to be despawned. var/orient_right = null // Flips the sprite. - var/time_till_despawn = 9000 // 15 minutes-ish safe period before being despawned. + // 15 minutes-ish safe period before being despawned. + var/time_till_despawn = 9000 // This is reduced by 90% if a player manually enters cryo + var/willing_time_divisor = 10 var/time_entered = 0 // Used to keep track of the safe period. var/obj/item/device/radio/intercom/announce // @@ -335,7 +337,7 @@ job_master.FreeRole(job) if(occupant.mind.objectives.len) - qdel(occupant.mind.objectives) + occupant.mind.objectives.Cut() occupant.mind.special_role = null else if(ticker.mode.name == "AutoTraitor") @@ -382,7 +384,12 @@ announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]") visible_message("\The [src] hums and hisses as it moves [occupant.real_name] into storage.") - // Delete the mob. + // Ghost and delete the mob. + if(!occupant.get_ghost(1)) + if(TOO_EARLY_TO_GHOST) + occupant.ghostize(0) // Players despawned too early may not re-enter the game + else + occupant.ghostize(1) qdel(occupant) occupant = null name = initial(name) @@ -404,6 +411,7 @@ var/willing = null //We don't want to allow people to be forced into despawning. var/mob/living/M = G:affecting + time_till_despawn = initial(time_till_despawn) if(!istype(M) || M.stat == DEAD) to_chat(user, "Dead people can not be put into cryo.") @@ -412,7 +420,7 @@ if(M.client) if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes") if(!M || !G || !G:affecting) return - willing = 1 + willing = willing_time_divisor else willing = 1 @@ -433,6 +441,8 @@ M.client.perspective = EYE_PERSPECTIVE M.client.eye = src + time_till_despawn = initial(time_till_despawn) / willing + else //because why the fuck would you keep going if the mob isn't in the pod to_chat(user, "You stop putting [M] into the cryopod.") return @@ -458,7 +468,7 @@ // Book keeping! log_admin("[key_name(M)] has entered a stasis pod.") - message_admins("[key_name_admin(user)] has entered a stasis pod. (JMP)") + message_admins("[key_name_admin(M)] has entered a stasis pod. (JMP)") //Despawning occurs when process() is called with an occupant without a client. src.add_fingerprint(M) @@ -502,11 +512,12 @@ var/willing = null //We don't want to allow people to be forced into despawning. + time_till_despawn = initial(time_till_despawn) if(L.client) if(alert(L,"Would you like to enter cryosleep?",,"Yes","No") == "Yes") if(!L) return - willing = 1 + willing = willing_time_divisor else willing = 1 @@ -523,6 +534,7 @@ to_chat(user, "\The [src] is in use.") return L.loc = src + time_till_despawn = initial(time_till_despawn) / willing if(L.client) L.client.perspective = EYE_PERSPECTIVE @@ -622,6 +634,7 @@ usr.client.eye = src usr.loc = src src.occupant = usr + time_till_despawn = initial(time_till_despawn) / willing_time_divisor if(orient_right) icon_state = "[occupied_icon_state]-r" diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index a0f6c9a08ce..f952f8f2bc3 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -109,7 +109,7 @@ D.safe = 1 else - for(var/obj/machinery/door/poddoor/M in world) + for(var/obj/machinery/door/poddoor/M in airlocks) if(M.id_tag == src.id) if(M.density) spawn( 0 ) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 394f29a1ccf..7248a5e1022 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -980,7 +980,7 @@ About the new airlock wires panel: wires = new(src) if(src.closeOtherId != null) spawn (5) - for(var/obj/machinery/door/airlock/A in world) + for(var/obj/machinery/door/airlock/A in airlocks) if(A.closeOtherId == src.closeOtherId && A != src) src.closeOther = A break @@ -1069,4 +1069,23 @@ About the new airlock wires panel: src.unlock() src.open() src.lock() - return + +/obj/machinery/door/airlock/hostile_lockdown(mob/origin) + // Must be powered and have working AI wire. + if(canAIControl(src) && !stat) + locked = FALSE //For airlocks that were bolted open. + safe = FALSE //DOOR CRUSH + close() + lock() //Bolt it! + electrified_until = -1 //Shock it! + if(origin) + shockedby += "\[[time_stamp()]\][origin](ckey:[origin.ckey])" + + +/obj/machinery/door/airlock/disable_lockdown() + // Must be powered and have working AI wire. + if(canAIControl(src) && !stat) + unlock() + electrified_until = 0 + open() + safe = TRUE \ No newline at end of file diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm index 9c4d881f378..e33d3e4d9c4 100644 --- a/code/game/machinery/doors/airlock_control.dm +++ b/code/game/machinery/doors/airlock_control.dm @@ -10,8 +10,7 @@ obj/machinery/door/airlock obj/machinery/door/airlock/process() if(arePowerSystemsOn() && cur_command) - spawn() - execute_current_command() + execute_current_command() else return PROCESS_KILL diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 6c9537667fb..8c5a1fd85fc 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -301,3 +301,11 @@ /obj/machinery/door/morgue icon = 'icons/obj/doors/doormorgue.dmi' + +/obj/machinery/door/proc/hostile_lockdown(mob/origin) + if(!stat) //So that only powered doors are closed. + close() //Close ALL the doors! + +/obj/machinery/door/proc/disable_lockdown() + if(!stat) //Opens only powered doors. + open() //Open everything! \ No newline at end of file diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index cbb9aabd20f..777c2c1bfd5 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -7,6 +7,7 @@ var/list/doppler_arrays = list() icon_state = "tdoppler" density = 1 anchored = 1 + atom_say_verb = "states coldly" /obj/machinery/doppler_array/New() ..() @@ -74,9 +75,8 @@ var/list/doppler_arrays = list() if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range) messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]." - for(var/mob/O in hearers(src, null)) - for(var/message in messages) - O.show_message("[src] states coldly, \"[message]\"",2) + for(var/message in messages) + atom_say(message) /obj/machinery/doppler_array/power_change() diff --git a/code/game/machinery/drying_rack.dm b/code/game/machinery/drying_rack.dm deleted file mode 100644 index 9ec3974483f..00000000000 --- a/code/game/machinery/drying_rack.dm +++ /dev/null @@ -1,105 +0,0 @@ -/obj/machinery/drying_rack - name = "drying rack" - desc = "A large rack with a heater built into the base. Used for drying things out." - icon = 'icons/obj/hydroponics.dmi' - icon_state = "drying_rack" - layer = 2.9 - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 50 - var/list/accepted = list() - var/running = 0 - var/volume = 100 - -/obj/machinery/drying_rack/New() - ..() - flags |= NOREACT - create_reagents(volume) - accepted = list(/obj/item/weapon/reagent_containers/food/snacks/grown/coffee_arabica, - /obj/item/weapon/reagent_containers/food/snacks/grown/coffee_robusta, - /obj/item/weapon/reagent_containers/food/snacks/grown/tobacco, - /obj/item/weapon/reagent_containers/food/snacks/grown/tobacco_space, - /obj/item/weapon/reagent_containers/food/snacks/grown/tea_aspera, - /obj/item/weapon/reagent_containers/food/snacks/grown/tea_astra, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/grapes, - /obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes) - - - -/obj/machinery/drying_rack/attackby(var/obj/item/W as obj, var/mob/user as mob, params) - if(is_type_in_list(W,accepted)) - if(!running) - if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/meat)) - user.unEquip(W) - del(W) - to_chat(user, "You add the meat to the drying rack.") - src.running = 1 - use_power = 2 - icon_state = "drying_rack_on" - sleep(60) - icon_state = "drying_rack" - new /obj/item/weapon/reagent_containers/food/snacks/sosjerky(src.loc) - use_power = 1 - src.running = 0 - return - if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown/grapes)) - user.unEquip(W) - del(W) - to_chat(user, "You add the grapes to the drying rack.") - src.running = 1 - use_power = 2 - icon_state = "drying_rack_on" - sleep(60) - icon_state = "drying_rack" - new /obj/item/weapon/reagent_containers/food/snacks/no_raisin(src.loc) - use_power = 1 - src.running = 0 - return - if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes)) - user.unEquip(W) - del(W) - to_chat(user, "You add the green grapes to the drying rack.") - src.running = 1 - use_power = 2 - icon_state = "drying_rack_on" - sleep(60) - icon_state = "drying_rack" - new /obj/item/weapon/reagent_containers/food/snacks/no_raisin(src.loc) - use_power = 1 - src.running = 0 - return - else - if(W:dry == 0) - var/J = W.type - var/obj/item/weapon/reagent_containers/food/snacks/grown/B = W - B.reagents.trans_to(src, B.reagents.total_volume) - to_chat(user, "You add the [W] to the drying rack.") - user.unEquip(W) - del(W) - src.running = 1 - use_power = 2 - icon_state = "drying_rack_on" - sleep(60) - icon_state = "drying_rack" - var/obj/item/weapon/reagent_containers/food/snacks/grown/D = new J(src.loc) - to_chat(user, "\blue You finish drying the [D]") - D.icon_state = "[D.icon_state]_dry" - D.dry = 1 - D.reagents.remove_any(50) - src.reagents.trans_to(D, src.reagents.total_volume) - use_power = 1 - src.running = 0 - return - else - to_chat(user, "\red That has already been dried!") - else - to_chat(user, "\red Please wait until the last item has dried.") - else - to_chat(user, "\red You cannot add that to the drying rack.") - - diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller.dm b/code/game/machinery/embedded_controller/airlock_docking_controller.dm deleted file mode 100644 index e94a975b91f..00000000000 --- a/code/game/machinery/embedded_controller/airlock_docking_controller.dm +++ /dev/null @@ -1,180 +0,0 @@ -//a docking port based on an airlock -/obj/machinery/embedded_controller/radio/airlock/docking_port - name = "docking port controller" - var/datum/computer/file/embedded_program/airlock/docking/airlock_program - var/datum/computer/file/embedded_program/docking/airlock/docking_program - tag_secure = 1 - -/obj/machinery/embedded_controller/radio/airlock/docking_port/initialize() - ..() - airlock_program = new/datum/computer/file/embedded_program/airlock/docking(src) - docking_program = new/datum/computer/file/embedded_program/docking/airlock(src, airlock_program) - program = docking_program - -/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( - "chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]), - "exterior_status" = airlock_program.memory["exterior_status"], - "interior_status" = airlock_program.memory["interior_status"], - "processing" = airlock_program.memory["processing"], - "docking_status" = docking_program.get_docking_status(), - "airlock_disabled" = !(docking_program.undocked() || docking_program.override_enabled), - "override_enabled" = docking_program.override_enabled, - ) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if(!ui) - ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/docking_port/Topic(href, href_list) - if(..()) - return - - usr.set_machine(src) - src.add_fingerprint(usr) - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - - - -//A docking controller for an airlock based docking port -/datum/computer/file/embedded_program/docking/airlock - var/datum/computer/file/embedded_program/airlock/docking/airlock_program - -/datum/computer/file/embedded_program/docking/airlock/New(var/obj/machinery/embedded_controller/M, var/datum/computer/file/embedded_program/airlock/docking/A) - ..(M) - airlock_program = A - airlock_program.master_prog = src - -/datum/computer/file/embedded_program/docking/airlock/receive_user_command(command) - if(command == "toggle_override") - if(override_enabled) - disable_override() - else - enable_override() - return - - ..(command) - airlock_program.receive_user_command(command) //pass along to subprograms - -/datum/computer/file/embedded_program/docking/airlock/process() - airlock_program.process() - ..() - -/datum/computer/file/embedded_program/docking/airlock/receive_signal(datum/signal/signal, receive_method, receive_param) - airlock_program.receive_signal(signal, receive_method, receive_param) //pass along to subprograms - ..(signal, receive_method, receive_param) - -//tell the docking port to start getting ready for docking - e.g. pressurize -/datum/computer/file/embedded_program/docking/airlock/prepare_for_docking() - airlock_program.begin_cycle_in() - -//are we ready for docking? -/datum/computer/file/embedded_program/docking/airlock/ready_for_docking() - return airlock_program.done_cycling() - -//we are docked, open the doors or whatever. -/datum/computer/file/embedded_program/docking/airlock/finish_docking() - airlock_program.enable_mech_regulators() - airlock_program.open_doors() - -//tell the docking port to start getting ready for undocking - e.g. close those doors. -/datum/computer/file/embedded_program/docking/airlock/prepare_for_undocking() - airlock_program.stop_cycling() - airlock_program.close_doors() - airlock_program.disable_mech_regulators() - -//are we ready for undocking? -/datum/computer/file/embedded_program/docking/airlock/ready_for_undocking() - var/ext_closed = airlock_program.check_exterior_door_secured() - var/int_closed = airlock_program.check_interior_door_secured() - return (ext_closed || int_closed) - -//An airlock controller to be used by the airlock-based docking port controller. -//Same as a regular airlock controller but allows disabling of the regular airlock functions when docking -/datum/computer/file/embedded_program/airlock/docking - var/datum/computer/file/embedded_program/docking/airlock/master_prog - -/datum/computer/file/embedded_program/airlock/docking/receive_user_command(command) - if(master_prog.undocked() || master_prog.override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled - ..(command) - -/datum/computer/file/embedded_program/airlock/docking/proc/enable_mech_regulators() - enable_mech_regulation() - -/datum/computer/file/embedded_program/airlock/docking/proc/disable_mech_regulators() - disable_mech_regulation() - -/datum/computer/file/embedded_program/airlock/docking/proc/open_doors() - toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open") - toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "open") - -/datum/computer/file/embedded_program/airlock/docking/cycleDoors(var/target) - if(master_prog.undocked() || master_prog.override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled - ..(target) - -/*** DEBUG VERBS *** - -/datum/computer/file/embedded_program/docking/proc/print_state() - to_chat(world, "id_tag: [id_tag]") - to_chat(world, "dock_state: [dock_state]") - to_chat(world, "control_mode: [control_mode]") - to_chat(world, "tag_target: [tag_target]") - to_chat(world, "response_sent: [response_sent]") - -/datum/computer/file/embedded_program/docking/post_signal(datum/signal/signal, comm_line) - to_chat(world, "Program [id_tag] sent a message!") - print_state() - to_chat(world, "[id_tag] sent command \"[signal.data["command"]]\" to \"[signal.data["recipient"]]\"") - ..(signal) - -/obj/machinery/embedded_controller/radio/airlock/docking_port/verb/view_state() - set category = "Debug" - set src in view(1) - src.program:print_state() - -/obj/machinery/embedded_controller/radio/airlock/docking_port/verb/spoof_signal(var/command as text, var/sender as text) - set category = "Debug" - set src in view(1) - var/datum/signal/signal = new - signal.data["tag"] = sender - signal.data["command"] = command - signal.data["recipient"] = id_tag - - src.program:receive_signal(signal) - -/obj/machinery/embedded_controller/radio/airlock/docking_port/verb/debug_init_dock(var/target as text) - set category = "Debug" - set src in view(1) - src.program:initiate_docking(target) - -/obj/machinery/embedded_controller/radio/airlock/docking_port/verb/debug_init_undock() - set category = "Debug" - set src in view(1) - src.program:initiate_undocking() - -*/ \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm deleted file mode 100644 index 8eeb93b8a8e..00000000000 --- a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm +++ /dev/null @@ -1,153 +0,0 @@ -//a controller for a docking port with multiple independent airlocks -//this is the master controller, that things will try to dock with. -/obj/machinery/embedded_controller/radio/docking_port_multi - name = "docking port controller" - - var/child_tags_txt - var/child_names_txt - var/list/child_names = list() - - var/datum/computer/file/embedded_program/docking/multi/docking_program - -/obj/machinery/embedded_controller/radio/docking_port_multi/initialize() - ..() - docking_program = new/datum/computer/file/embedded_program/docking/multi(src) - program = docking_program - - var/list/names = splittext(child_names_txt, ";") - var/list/tags = splittext(child_tags_txt, ";") - - if(names.len == tags.len) - for(var/i = 1; i <= tags.len; i++) - child_names[tags[i]] = names[i] - - -/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - var/list/airlocks[child_names.len] - var/i = 1 - for(var/child_tag in child_names) - airlocks[i++] = list("name"=child_names[child_tag], "override_enabled"=(docking_program.children_override[child_tag] == "enabled")) - - data = list( - "docking_status" = docking_program.get_docking_status(), - "airlocks" = airlocks, - ) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if(!ui) - ui = new(user, src, ui_key, "multi_docking_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list) - return - - - -//a docking port based on an airlock -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi - name = "docking port controller" - var/master_tag //for mapping - var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program - tag_secure = 1 - -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/initialize() - ..() - airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src) - program = airlock_program - -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( - "chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]), - "exterior_status" = airlock_program.memory["exterior_status"], - "interior_status" = airlock_program.memory["interior_status"], - "processing" = airlock_program.memory["processing"], - "docking_status" = airlock_program.master_status, - "airlock_disabled" = (airlock_program.docking_enabled && !airlock_program.override_enabled), - "override_enabled" = airlock_program.override_enabled, - ) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if(!ui) - ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list) - if(..()) - return - - usr.set_machine(src) - src.add_fingerprint(usr) - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - - - -/*** DEBUG VERBS *** - -/datum/computer/file/embedded_program/docking/multi/proc/print_state() - to_chat(world, "id_tag: [id_tag]") - to_chat(world, "dock_state: [dock_state]") - to_chat(world, "control_mode: [control_mode]") - to_chat(world, "tag_target: [tag_target]") - to_chat(world, "response_sent: [response_sent]") - -/datum/computer/file/embedded_program/docking/multi/post_signal(datum/signal/signal, comm_line) - to_chat(world, "Program [id_tag] sent a message!") - print_state() - to_chat(world, "[id_tag] sent command \"[signal.data["command"]]\" to \"[signal.data["recipient"]]\"") - ..(signal) - -/obj/machinery/embedded_controller/radio/docking_port_multi/verb/view_state() - set category = "Debug" - set src in view(1) - src.program:print_state() - -/obj/machinery/embedded_controller/radio/docking_port_multi/verb/spoof_signal(var/command as text, var/sender as text) - set category = "Debug" - set src in view(1) - var/datum/signal/signal = new - signal.data["tag"] = sender - signal.data["command"] = command - signal.data["recipient"] = id_tag - - src.program:receive_signal(signal) - -/obj/machinery/embedded_controller/radio/docking_port_multi/verb/debug_init_dock(var/target as text) - set category = "Debug" - set src in view(1) - src.program:initiate_docking(target) - -/obj/machinery/embedded_controller/radio/docking_port_multi/verb/debug_init_undock() - set category = "Debug" - set src in view(1) - src.program:initiate_undocking() - -*/ diff --git a/code/game/machinery/embedded_controller/docking_program.dm b/code/game/machinery/embedded_controller/docking_program.dm deleted file mode 100644 index 725ec6a337b..00000000000 --- a/code/game/machinery/embedded_controller/docking_program.dm +++ /dev/null @@ -1,286 +0,0 @@ - -#define STATE_UNDOCKED 0 -#define STATE_DOCKING 1 -#define STATE_UNDOCKING 2 -#define STATE_DOCKED 3 - -#define MODE_NONE 0 -#define MODE_SERVER 1 -#define MODE_CLIENT 2 //The one who initiated the docking, and who can initiate the undocking. The server cannot initiate undocking, and is the one responsible for deciding to accept a docking request and signals when docking and undocking is complete. (Think server == station, client == shuttle) - -#define MESSAGE_RESEND_TIME 5 //how long (in seconds) do we wait before resending a message - -/* - *** STATE TABLE *** - - MODE_CLIENT|STATE_UNDOCKED sent a request for docking and now waiting for a reply. - MODE_CLIENT|STATE_DOCKING server told us they are OK to dock, waiting for our docking port to be ready. - MODE_CLIENT|STATE_DOCKED idle - docked as client. - MODE_CLIENT|STATE_UNDOCKING we are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking. - - MODE_SERVER|STATE_UNDOCKED should never happen. - MODE_SERVER|STATE_DOCKING someone requested docking, we are waiting for our docking port to be ready. - MODE_SERVER|STATE_DOCKED idle - docked as server - MODE_SERVER|STATE_UNDOCKING client requested undocking, we are waiting for our docking port to be ready. - - MODE_NONE|STATE_UNDOCKED idle - not docked. - MODE_NONE|anything else should never happen. - - *** Docking Signals *** - - Docking - Client sends request_dock - - Server sends confirm_dock to say that yes, we will serve your request - When client is ready, sends confirm_dock - Server sends confirm_dock back to indicate that docking is complete - - Undocking - Client sends request_undock - When client is ready, sends confirm_undock - Server sends confirm_undock back to indicate that docking is complete - - Note that in both cases each side exchanges confirm_dock before the docking operation is considered done. - The client first sends a confirm message to indicate it is ready, and then finally the server will send it's - confirm message to indicate that the operation is complete. - - Note also that when docking, the server sends an additional confirm message. This is because before docking, - the server and client do not have a defined relationship. Before undocking, the server and client are already - related to each other, thus the extra confirm message is not needed. - - *** Override, what is it? *** - - The purpose of enabling the override is to prevent the docking program from automatically doing things with the docking port when docking or undocking. - Maybe the shuttle is full of plasma for some reason, and you don't want the door to automatically open, or the airlock to cycle. - This means that the prepare_for_docking/undocking and finish_docking/undocking procs don't get called. - - The docking controller will still check the state of the docking port, and thus prevent the shuttle from launching unless they force the launch (handling forced - launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock - (which usually just means closing and locking the doors). - - In line with this, docking controllers should prevent players from manually doing things when the override is NOT enabled. -*/ - - -/datum/computer/file/embedded_program/docking - var/tag_target //the tag of the docking controller that we are trying to dock with - var/dock_state = STATE_UNDOCKED - var/control_mode = MODE_NONE - var/response_sent = 0 //so we don't spam confirmation messages - var/resend_counter = 0 //for periodically resending confirmation messages in case they are missed - - var/override_enabled = 0 //when enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually - var/received_confirm = 0 //for undocking, whether the server has recieved a confirmation from the client - -/datum/computer/file/embedded_program/docking/receive_signal(datum/signal/signal, receive_method, receive_param) - var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id - var/command = signal.data["command"] - var/recipient = signal.data["recipient"] //the intended recipient of the docking signal - - if(recipient != id_tag) - return //this signal is not for us - - switch(command) - if("confirm_dock") - if(control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKED && receive_tag == tag_target) - dock_state = STATE_DOCKING - broadcast_docking_status() - if(!override_enabled) - prepare_for_docking() - - else if(control_mode == MODE_CLIENT && dock_state == STATE_DOCKING && receive_tag == tag_target) - dock_state = STATE_DOCKED - broadcast_docking_status() - if(!override_enabled) - finish_docking() //client done docking! - response_sent = 0 - else if(control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) //client just sent us the confirmation back, we're done with the docking process - received_confirm = 1 - - if("request_dock") - if(control_mode == MODE_NONE && dock_state == STATE_UNDOCKED) - control_mode = MODE_SERVER - - dock_state = STATE_DOCKING - broadcast_docking_status() - - tag_target = receive_tag - if(!override_enabled) - prepare_for_docking() - send_docking_command(tag_target, "confirm_dock") //acknowledge the request - - if("confirm_undock") - if(control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKING && receive_tag == tag_target) - if(!override_enabled) - finish_undocking() - reset() //client is done undocking! - else if(control_mode == MODE_SERVER && dock_state == STATE_UNDOCKING && receive_tag == tag_target) - received_confirm = 1 - - if("request_undock") - if(control_mode == MODE_SERVER && dock_state == STATE_DOCKED && receive_tag == tag_target) - dock_state = STATE_UNDOCKING - broadcast_docking_status() - - if(!override_enabled) - prepare_for_undocking() - - if("dock_error") - if(receive_tag == tag_target) - reset() - -/datum/computer/file/embedded_program/docking/process() - switch(dock_state) - if(STATE_DOCKING) //waiting for our docking port to be ready for docking - if(ready_for_docking()) - if(control_mode == MODE_CLIENT) - if(!response_sent) - send_docking_command(tag_target, "confirm_dock") //tell the server we're ready - response_sent = 1 - - else if(control_mode == MODE_SERVER && received_confirm) - send_docking_command(tag_target, "confirm_dock") //tell the client we are done docking. - - dock_state = STATE_DOCKED - broadcast_docking_status() - - if(!override_enabled) - finish_docking() //server done docking! - response_sent = 0 - received_confirm = 0 - - if(STATE_UNDOCKING) - if(ready_for_undocking()) - if(control_mode == MODE_CLIENT) - if(!response_sent) - send_docking_command(tag_target, "confirm_undock") //tell the server we are OK to undock. - response_sent = 1 - - else if(control_mode == MODE_SERVER && received_confirm) - send_docking_command(tag_target, "confirm_undock") //tell the client we are done undocking. - if(!override_enabled) - finish_undocking() - reset() //server is done undocking! - - if(response_sent || resend_counter > 0) - resend_counter++ - - if(resend_counter >= MESSAGE_RESEND_TIME || (dock_state != STATE_DOCKING && dock_state != STATE_UNDOCKING)) - response_sent = 0 - resend_counter = 0 - - //handle invalid states - if(control_mode == MODE_NONE && dock_state != STATE_UNDOCKED) - if(tag_target) - send_docking_command(tag_target, "dock_error") - reset() - if(control_mode == MODE_SERVER && dock_state == STATE_UNDOCKED) - control_mode = MODE_NONE - - -/datum/computer/file/embedded_program/docking/proc/initiate_docking(var/target) - if(dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) //must be undocked and not serving another request to begin a new docking handshake - return - - tag_target = target - control_mode = MODE_CLIENT - - send_docking_command(tag_target, "request_dock") - -/datum/computer/file/embedded_program/docking/proc/initiate_undocking() - if(dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) //must be docked and must be client to start undocking - return - - dock_state = STATE_UNDOCKING - broadcast_docking_status() - - if(!override_enabled) - prepare_for_undocking() - - send_docking_command(tag_target, "request_undock") - -//tell the docking port to start getting ready for docking - e.g. pressurize -/datum/computer/file/embedded_program/docking/proc/prepare_for_docking() - return - -//are we ready for docking? -/datum/computer/file/embedded_program/docking/proc/ready_for_docking() - return 1 - -//we are docked, open the doors or whatever. -/datum/computer/file/embedded_program/docking/proc/finish_docking() - return - -//tell the docking port to start getting ready for undocking - e.g. close those doors. -/datum/computer/file/embedded_program/docking/proc/prepare_for_undocking() - return - -//we are docked, open the doors or whatever. -/datum/computer/file/embedded_program/docking/proc/finish_undocking() - return - -//are we ready for undocking? -/datum/computer/file/embedded_program/docking/proc/ready_for_undocking() - return 1 - -/datum/computer/file/embedded_program/docking/proc/enable_override() - override_enabled = 1 - -/datum/computer/file/embedded_program/docking/proc/disable_override() - override_enabled = 0 - -/datum/computer/file/embedded_program/docking/proc/reset() - dock_state = STATE_UNDOCKED - broadcast_docking_status() - - control_mode = MODE_NONE - tag_target = null - response_sent = 0 - received_confirm = 0 - -/datum/computer/file/embedded_program/docking/proc/force_undock() -// to_chat(world, "[id_tag]: forcing undock") - if(tag_target) - send_docking_command(tag_target, "dock_error") - reset() - -/datum/computer/file/embedded_program/docking/proc/docked() - return (dock_state == STATE_DOCKED) - -/datum/computer/file/embedded_program/docking/proc/undocked() - return (dock_state == STATE_UNDOCKED) - -//returns 1 if we are saftely undocked (and the shuttle can leave) -/datum/computer/file/embedded_program/docking/proc/can_launch() - return undocked() - -/datum/computer/file/embedded_program/docking/proc/send_docking_command(var/recipient, var/command) - var/datum/signal/signal = new - signal.data["tag"] = id_tag - signal.data["command"] = command - signal.data["recipient"] = recipient - post_signal(signal) - -/datum/computer/file/embedded_program/docking/proc/broadcast_docking_status() - var/datum/signal/signal = new - signal.data["tag"] = id_tag - signal.data["dock_status"] = get_docking_status() - post_signal(signal) - -//this is mostly for NanoUI -/datum/computer/file/embedded_program/docking/proc/get_docking_status() - switch(dock_state) - if(STATE_UNDOCKED) return "undocked" - if(STATE_DOCKING) return "docking" - if(STATE_UNDOCKING) return "undocking" - if(STATE_DOCKED) return "docked" - - -#undef STATE_UNDOCKED -#undef STATE_DOCKING -#undef STATE_UNDOCKING -#undef STATE_DOCKED - -#undef MODE_NONE -#undef MODE_SERVER -#undef MODE_CLIENT \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/docking_program_multi.dm b/code/game/machinery/embedded_controller/docking_program_multi.dm deleted file mode 100644 index 0a3d9228435..00000000000 --- a/code/game/machinery/embedded_controller/docking_program_multi.dm +++ /dev/null @@ -1,223 +0,0 @@ -/* - These programs are for docking controllers that consist of multiple independent airlocks - Each airlock has an airlock controller running the child program, and there is one docking controller running the master program -*/ - -/* - the master program -*/ -/datum/computer/file/embedded_program/docking/multi - var/list/children_tags - var/list/children_ready - var/list/children_override - -/datum/computer/file/embedded_program/docking/multi/New(var/obj/machinery/embedded_controller/M) - ..(M) - - if(istype(M,/obj/machinery/embedded_controller/radio/docking_port_multi)) //if our parent controller is the right type, then we can auto-init stuff at construction - var/obj/machinery/embedded_controller/radio/docking_port_multi/controller = M - //parse child_tags_txt and create child tags - children_tags = splittext(controller.child_tags_txt, ";") - - children_ready = list() - children_override = list() - for(var/child_tag in children_tags) - children_ready[child_tag] = 0 - children_override[child_tag] = "disabled" - -/datum/computer/file/embedded_program/docking/multi/proc/clear_children_ready_status() - for(var/child_tag in children_tags) - children_ready[child_tag] = 0 - -/datum/computer/file/embedded_program/docking/multi/receive_signal(datum/signal/signal, receive_method, receive_param) - var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id - var/command = signal.data["command"] - var/recipient = signal.data["recipient"] //the intended recipient of the docking signal - - if(receive_tag in children_tags) - - //track children status - if(signal.data["override_status"]) - children_override[receive_tag] = signal.data["override_status"] - - if(recipient == id_tag) - switch(command) - if("ready_for_docking") - children_ready[receive_tag] = 1 - if("ready_for_undocking") - children_ready[receive_tag] = 1 - if("status_override_enabled") - children_override[receive_tag] = 1 - if("status_override_disabled") - children_override[receive_tag] = 0 - - ..(signal, receive_method, receive_param) - -/datum/computer/file/embedded_program/docking/multi/prepare_for_docking() - //clear children ready status - clear_children_ready_status() - - //tell children to prepare for docking - for(var/child_tag in children_tags) - send_docking_command(child_tag, "prepare_for_docking") - -/datum/computer/file/embedded_program/docking/multi/ready_for_docking() - //check children ready status - for(var/child_tag in children_tags) - if(!children_ready[child_tag]) - return 0 - return 1 - -/datum/computer/file/embedded_program/docking/multi/finish_docking() - //tell children to finish docking - for(var/child_tag in children_tags) - send_docking_command(child_tag, "finish_docking") - - //clear ready flags - clear_children_ready_status() - -/datum/computer/file/embedded_program/docking/multi/prepare_for_undocking() - //clear children ready status - clear_children_ready_status() - - //tell children to prepare for undocking - for(var/child_tag in children_tags) - send_docking_command(child_tag, "prepare_for_undocking") - -/datum/computer/file/embedded_program/docking/multi/ready_for_undocking() - //check children ready status - for(var/child_tag in children_tags) - if(!children_ready[child_tag]) - return 0 - return 1 - -/datum/computer/file/embedded_program/docking/multi/finish_undocking() - //tell children to finish undocking - for(var/child_tag in children_tags) - send_docking_command(child_tag, "finish_undocking") - - //clear ready flags - clear_children_ready_status() - - - - -/* - the child program - technically should be "slave" but eh... I'm too politically correct. -*/ -/datum/computer/file/embedded_program/airlock/multi_docking - var/master_tag - - var/master_status = "undocked" - var/override_enabled = 0 - var/docking_enabled = 0 - var/docking_mode = 0 //0 = docking, 1 = undocking - var/response_sent = 0 - -/datum/computer/file/embedded_program/airlock/multi_docking/New(var/obj/machinery/embedded_controller/M) - ..(M) - - if(istype(M, /obj/machinery/embedded_controller/radio/airlock/docking_port_multi)) //if our parent controller is the right type, then we can auto-init stuff at construction - var/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/controller = M - src.master_tag = controller.master_tag - -/datum/computer/file/embedded_program/airlock/multi_docking/receive_user_command(command) - if(command == "toggle_override") - if(override_enabled) - override_enabled = 0 - broadcast_override_status() - else - override_enabled = 1 - broadcast_override_status() - return - - if(!docking_enabled|| override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled - ..(command) - -/datum/computer/file/embedded_program/airlock/multi_docking/receive_signal(datum/signal/signal, receive_method, receive_param) - ..() - - var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id - var/command = signal.data["command"] - var/recipient = signal.data["recipient"] //the intended recipient of the docking signal - - if(receive_tag != master_tag) - return //only respond to master - - //track master's status - if(signal.data["dock_status"]) - master_status = signal.data["dock_status"] - - if(recipient != id_tag) - return //this signal is not for us - - switch(command) - if("prepare_for_docking") - docking_enabled = 1 - docking_mode = 0 - response_sent = 0 - - if(!override_enabled) - begin_cycle_in() - - if("prepare_for_undocking") - docking_mode = 1 - response_sent = 0 - - if(!override_enabled) - stop_cycling() - close_doors() - disable_mech_regulation() - - if("finish_docking") - if(!override_enabled) - enable_mech_regulation() - open_doors() - - if("finish_undocking") - docking_enabled = 0 - -/datum/computer/file/embedded_program/airlock/multi_docking/process() - ..() - - if(docking_enabled && !response_sent) - - switch(docking_mode) - if(0) //docking - if(ready_for_docking()) - send_signal_to_master("ready_for_docking") - response_sent = 1 - if(1) //undocking - if(ready_for_undocking()) - send_signal_to_master("ready_for_undocking") - response_sent = 1 - -//checks if we are ready for docking -/datum/computer/file/embedded_program/airlock/multi_docking/proc/ready_for_docking() - return done_cycling() - -//checks if we are ready for undocking -/datum/computer/file/embedded_program/airlock/multi_docking/proc/ready_for_undocking() - return check_doors_secured() - -/datum/computer/file/embedded_program/airlock/multi_docking/proc/open_doors() - toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open") - toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "open") - -/datum/computer/file/embedded_program/airlock/multi_docking/cycleDoors(var/target) - if(!docking_enabled|| override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled - ..(target) - -/datum/computer/file/embedded_program/airlock/multi_docking/proc/send_signal_to_master(var/command) - var/datum/signal/signal = new - signal.data["tag"] = id_tag - signal.data["command"] = command - signal.data["recipient"] = master_tag - post_signal(signal) - -/datum/computer/file/embedded_program/airlock/multi_docking/proc/broadcast_override_status() - var/datum/signal/signal = new - signal.data["tag"] = id_tag - signal.data["override_status"] = override_enabled? "enabled" : "disabled" - post_signal(signal) diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm deleted file mode 100644 index 996a56b92ac..00000000000 --- a/code/game/machinery/embedded_controller/simple_docking_controller.dm +++ /dev/null @@ -1,158 +0,0 @@ -//a docking port that uses a single door -/obj/machinery/embedded_controller/radio/simple_docking_controller - name = "docking hatch controller" - var/tag_door - var/datum/computer/file/embedded_program/docking/simple/docking_program - -/obj/machinery/embedded_controller/radio/simple_docking_controller/initialize() - ..() - docking_program = new/datum/computer/file/embedded_program/docking/simple(src) - program = docking_program - -/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( - "docking_status" = docking_program.get_docking_status(), - "override_enabled" = docking_program.override_enabled, - "door_state" = docking_program.memory["door_status"]["state"], - "door_lock" = docking_program.memory["door_status"]["lock"], - ) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if(!ui) - ui = new(user, src, ui_key, "simple_docking_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list) - if(..()) - return 1 - - usr.set_machine(src) - src.add_fingerprint(usr) - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("force_door") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 0 - - -//A docking controller program for a simple door based docking port -/datum/computer/file/embedded_program/docking/simple - var/tag_door - -/datum/computer/file/embedded_program/docking/simple/New(var/obj/machinery/embedded_controller/M) - ..(M) - memory["door_status"] = list(state = "closed", lock = "locked") //assume closed and locked in case the doors dont report in - - if(istype(M, /obj/machinery/embedded_controller/radio/simple_docking_controller)) - var/obj/machinery/embedded_controller/radio/simple_docking_controller/controller = M - - tag_door = controller.tag_door? controller.tag_door : "[id_tag]_hatch" - - spawn(10) - signal_door("update") //signals connected doors to update their status - - -/datum/computer/file/embedded_program/docking/simple/receive_signal(datum/signal/signal, receive_method, receive_param) - var/receive_tag = signal.data["tag"] - - if(!receive_tag) return - - if(receive_tag==tag_door) - memory["door_status"]["state"] = signal.data["door_status"] - memory["door_status"]["lock"] = signal.data["lock_status"] - - ..(signal, receive_method, receive_param) - -/datum/computer/file/embedded_program/docking/simple/receive_user_command(command) - switch(command) - if("force_door") - if(override_enabled) - if(memory["door_status"]["state"] == "open") - close_door() - else - open_door() - if("toggle_override") - if(override_enabled) - disable_override() - else - enable_override() - - -/datum/computer/file/embedded_program/docking/simple/proc/signal_door(var/command) - var/datum/signal/signal = new - signal.data["tag"] = tag_door - signal.data["command"] = command - post_signal(signal) - -/datum/computer/file/embedded_program/docking/simple/proc/open_door() - if(memory["door_status"]["state"] == "closed") - signal_door("secure_open") - else if(memory["door_status"]["lock"] == "unlocked") - signal_door("lock") - -/datum/computer/file/embedded_program/docking/simple/proc/close_door() - if(memory["door_status"]["state"] == "open") - signal_door("secure_close") - else if(memory["door_status"]["lock"] == "unlocked") - signal_door("lock") - -//tell the docking port to start getting ready for docking - e.g. pressurize -/datum/computer/file/embedded_program/docking/simple/prepare_for_docking() - return //don't need to do anything - -//are we ready for docking? -/datum/computer/file/embedded_program/docking/simple/ready_for_docking() - return 1 //don't need to do anything - -//we are docked, open the doors or whatever. -/datum/computer/file/embedded_program/docking/simple/finish_docking() - open_door() - -//tell the docking port to start getting ready for undocking - e.g. close those doors. -/datum/computer/file/embedded_program/docking/simple/prepare_for_undocking() - close_door() - -//are we ready for undocking? -/datum/computer/file/embedded_program/docking/simple/ready_for_undocking() - return (memory["door_status"]["state"] == "closed" && memory["door_status"]["lock"] == "locked") - -/*** DEBUG VERBS *** - -/obj/machinery/embedded_controller/radio/simple_docking_controller/verb/view_state() - set category = "Debug" - set src in view(1) - src.program:print_state() - -/obj/machinery/embedded_controller/radio/simple_docking_controller/verb/spoof_signal(var/command as text, var/sender as text) - set category = "Debug" - set src in view(1) - var/datum/signal/signal = new - signal.data["tag"] = sender - signal.data["command"] = command - signal.data["recipient"] = id_tag - - src.program:receive_signal(signal) - -/obj/machinery/embedded_controller/radio/simple_docking_controller/verb/debug_init_dock(var/target as text) - set category = "Debug" - set src in view(1) - src.program:initiate_docking(target) - -/obj/machinery/embedded_controller/radio/simple_docking_controller/verb/debug_init_undock() - set category = "Debug" - set src in view(1) - src.program:initiate_undocking() - -*/ diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 45b515734f7..ffa35c963d0 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -49,10 +49,17 @@ FIRE ALARM else icon_state = "fire0" +/obj/machinery/firealarm/emag_act(mob/user) + if(!emagged) + emagged = 1 + if(user) + user.visible_message("Sparks fly out of the [src]!", + "You emag [src], disabling its thermal sensors.") + playsound(loc, 'sound/effects/sparks4.ogg', 50, 1) + /obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) - if(detecting) - if(temperature > T0C+200) - alarm() // added check of detector status here + if(!emagged && detecting && temperature > T0C + 200) + alarm() // added check of detector status here /obj/machinery/firealarm/attack_ai(mob/user as mob) src.add_hiddenprint(user) @@ -148,11 +155,6 @@ FIRE ALARM updateDialog() last_process = world.timeofday - if(locate(/obj/effect/hotspot) in loc) - alarm() - - return - /obj/machinery/firealarm/power_change() if(powered(ENVIRON)) stat &= ~NOPOWER @@ -293,6 +295,8 @@ FIRE ALARM pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + // TODO: Tie into space manager + // also hwat if(z == ZLEVEL_STATION || ZLEVEL_ASTEROID == 5) if(security_level) src.overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 53977708650..cee7706d256 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -19,6 +19,12 @@ src.cell = new(src) ..() +/obj/machinery/floodlight/Destroy() + if(cell) + qdel(cell) + cell = null + return ..() + /obj/machinery/floodlight/proc/updateicon() icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]" @@ -31,7 +37,7 @@ set_light(0) src.visible_message("[src] shuts down due to lack of power!") return - + /obj/machinery/floodlight/attack_ai(mob/user as mob) return diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index abe99777410..53e85ba72c4 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -108,21 +108,8 @@ var/const/HOLOPAD_MODE = 0 /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ /obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb, datum/language/speaking) - if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. - if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. - if(speaking) - text = speaking.scramble(text) - else - text = stars(text) - var/name_used = M.GetVoice() - //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. - var/rendered - if(speaking) - rendered = "Holopad received, [name_used] [speaking.format_message(text, verb)]" - else - rendered = "Holopad received, [name_used] [verb], \"[text]\"" - master.show_message(rendered, 2) - return + if(M && hologram && master)//Master is mostly a safety in case lag hits or something. + master.relay_speech(M, text, verb, speaking) /obj/machinery/hologram/holopad/hear_message(mob/living/M, text) if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index c0ecd475f5e..17552c3fe1c 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -116,6 +116,7 @@ Class Procs: var/interact_offline = 0 // Can the machine be interacted with while de-powered. var/use_log = list() var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST. + atom_say_verb = "beeps" /obj/machinery/initialize() addAtProcessing() @@ -418,17 +419,6 @@ Class Procs: return 1 return 0 -/obj/machinery/proc/state(var/msg) - for(var/mob/O in hearers(src, null)) - O.show_message("[bicon(src)] [msg]", 2) - -/obj/machinery/proc/ping(text=null) - if(!text) - text = "\The [src] pings." - - state(text, "blue") - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - /obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/part_replacer/W) var/shouldplaysound = 0 if(istype(W) && component_parts) @@ -544,6 +534,8 @@ Class Procs: return 0 if(!prob(prb)) return 0 + if((TK in user.mutations) && !Adjacent(user)) + return 0 var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread s.set_up(5, 1, src) s.start() @@ -556,6 +548,9 @@ Class Procs: /obj/machinery/proc/construction() return +/obj/machinery/proc/can_be_overridden() + . = 1 + /obj/machinery/tesla_act(var/power) ..() if(prob(85)) diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 5b6cfb5e73d..3d980e769e7 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -26,11 +26,13 @@ var/turf/T = loc hide(T.intact) - if(codes["patrol"]) + if(!codes || !codes.len) + log_debug("Empty codes datum at ([x],[y],[z])") + if("patrol" in codes) if(!navbeacons["[z]"]) navbeacons["[z]"] = list() navbeacons["[z]"] += src //Register with the patrol list! - if(codes["delivery"]) + if("delivery" in codes) deliverybeacons += src deliverybeacontags += location @@ -39,6 +41,15 @@ deliverybeacons -= src return ..() +/obj/machinery/navbeacon/serialize() + var/list/data = ..() + data["codes"] = codes + return data + +/obj/machinery/navbeacon/deserialize(list/data) + codes = data["codes"] + ..() + // set the transponder codes assoc list from codes_txt /obj/machinery/navbeacon/proc/set_codes() if(!codes_txt) @@ -201,4 +212,4 @@ Transponder Codes:

    "} codes[newkey] = newval - updateDialog() \ No newline at end of file + updateDialog() diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 3a6ef2dbd81..b96f42e4441 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -979,11 +979,9 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob, pa // return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. /obj/machinery/newscaster/proc/newsAlert(var/news_call) //This isn't Agouri's work, for it is ugly and vile. - var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ if(news_call) - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"[news_call]\"",2) + atom_say("Breaking news from [news_call]!") src.alert = 1 src.update_icon() spawn(300) @@ -992,7 +990,6 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob, pa if(!silence) playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1) else - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Attention! Wanted issue distributed!\"",2) + atom_say("Attention! Wanted issue distributed!") playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1) return diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 9b2515e8914..c0e8f7ac20d 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -276,7 +276,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() update_icon() if(!src.silent) playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1) - state(title) + atom_say(title) switch(priority) if(2) // High diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index ce5ca3ce85d..68c4ab10a34 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -19,6 +19,12 @@ update_icon() return +/obj/machinery/space_heater/Destroy() + if(cell) + qdel(cell) + cell = null + return ..() + /obj/machinery/space_heater/update_icon() overlays.Cut() icon_state = "sheater[on]" diff --git a/code/game/machinery/supply_display.dm b/code/game/machinery/supply_display.dm index 3b55d8423f7..caf0c9c67d9 100644 --- a/code/game/machinery/supply_display.dm +++ b/code/game/machinery/supply_display.dm @@ -5,6 +5,7 @@ /obj/machinery/status_display/supply_display/update() if(!..() && mode == STATUS_DISPLAY_CUSTOM) if(shuttle_master.supply.mode == SHUTTLE_IDLE) + // TODO: Tie into space manager if(shuttle_master.supply.z == ZLEVEL_STATION) message1 = "CARGO" message2 = "Docked" diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index db4cb0271c0..bf4300351fa 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -182,6 +182,7 @@ item_state = "eshield0" w_class = 3 origin_tech = "syndicate=6;combat=5" + burn_state = FLAMMABLE //Burnable (but the casing isn't) var/adminlog = null /obj/item/weapon/bombcore/ex_act(severity) //Little boom can chain a big boom diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 4d90971f003..7ddb0f4b963 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -439,6 +439,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(data == 1) for(var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) var/turf/position = get_turf(R) + // TODO: Tie into space manager if(position && position.z == level) receive |= R.send_hear(display_freq, level) @@ -451,6 +452,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(istype(R, /obj/item/device/radio/headset)) continue var/turf/position = get_turf(R) + // TODO: Tie into space manager if(position && position.z == level) receive |= R.send_hear(display_freq) @@ -462,6 +464,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(freq) for(var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"]) var/turf/position = get_turf(R) + // TODO: Tie into space manager if(position && position.z == level) receive |= R.send_hear(freq) @@ -471,6 +474,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else for(var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) var/turf/position = get_turf(R) + // TODO: Tie into space manager if(position && position.z == level) receive |= R.send_hear(display_freq) @@ -597,6 +601,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept /atom/proc/test_telecomms() var/datum/signal/signal = src.telecomms_process() var/turf/position = get_turf(src) + // TODO: Tie into space manager return (position.z in signal.data["level"]) && signal.data["done"] /atom/proc/telecomms_process(var/do_sleep = 1) @@ -615,6 +620,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept "type" = 4, // determines what type of radio input it is: test broadcast "reject" = 0, "done" = 0, + // TODO: Tie into space manager "level" = pos.z // The level it is being broadcasted at. ) signal.frequency = PUB_FREQ// Common channel @@ -630,4 +636,3 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept //log_to_dd("Level: [signal.data["level"]] - Done: [signal.data["done"]]") return signal - diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index da9fe5a046e..0c0dfd178fe 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -180,6 +180,7 @@ var/turf/position = get_turf(src) // Toggle on/off getting signals from the station or the current Z level + // TODO: Tie into space manager if(src.listening_level == ZLEVEL_STATION) // equals the station src.listening_level = position.z return 1 @@ -393,4 +394,3 @@ if(issilicon(user) || in_range(user, src)) return 1 return 0 - diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 787483ac45d..22c7863a3bb 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -56,40 +56,17 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() continue if(amount && send_count >= amount) break + // TODO: Tie into space manager if(machine.loc.z != listening_level) if(long_range_link == 0 && machine.long_range_link == 0) continue // If we're sending a copy, be sure to create the copy for EACH machine and paste the data - var/datum/signal/copy = new + var/datum/signal/copy if(copysig) - + copy = new copy.transmission_method = 2 copy.frequency = signal.frequency - // Copy the main data contents! Workaround for some nasty bug where the actual array memory is copied and not its contents. - copy.data = list( - - "mob" = signal.data["mob"], - "mobtype" = signal.data["mobtype"], - "realname" = signal.data["realname"], - "name" = signal.data["name"], - "job" = signal.data["job"], - "key" = signal.data["key"], - "vmessage" = signal.data["vmessage"], - "vname" = signal.data["vname"], - "vmask" = signal.data["vmask"], - "compression" = signal.data["compression"], - "message" = signal.data["message"], - "connection" = signal.data["connection"], - "radio" = signal.data["radio"], - "slow" = signal.data["slow"], - "traffic" = signal.data["traffic"], - "type" = signal.data["type"], - "server" = signal.data["server"], - "reject" = signal.data["reject"], - "level" = signal.data["level"], - "verb" = signal.data["verb"], - "language" = signal.data["language"] - ) + copy.data = signal.data.Copy() // Keep the "original" signal constant if(!signal.data["original"]) @@ -97,15 +74,11 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() else copy.data["original"] = signal.data["original"] - else - qdel(copy) - - send_count++ if(machine.is_freq_listening(signal)) machine.traffic++ - if(copysig && copy) + if(copysig) machine.receive_information(copy, src) else machine.receive_information(signal, src) @@ -142,6 +115,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() if(!listening_level) //Defaults to our Z level! var/turf/position = get_turf(src) + // TODO: Tie into space manager listening_level = position.z /obj/machinery/telecomms/initialize() @@ -167,6 +141,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) var/turf/position = get_turf(src) var/turf/T_position = get_turf(T) + // TODO: Tie into space manager if((position.z == T_position.z) || (src.long_range_link && T.long_range_link)) for(var/x in autolinkers) if(T.autolinkers.Find(x)) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 63aeb4e25ee..6ecc675fdef 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -182,7 +182,8 @@ var/turf/T = get_turf(R) if(!T) continue - if((T.z in config.admin_levels) || T.z > 7) + // TODO: Tie into space manager + if((T.z in config.admin_levels) || T.z > ZLEVEL_EMPTY) continue if(R.syndicate == 1 && emagged == 0) continue @@ -203,6 +204,7 @@ continue var/turf/T = get_turf(M) if(!T) continue + // TODO: Tie into space manager if((T.z in config.admin_levels)) continue var/tmpname = M.real_name if(areaindex[tmpname]) @@ -225,7 +227,8 @@ var/turf/T = get_turf(R) if(!T || !R.teleporter_hub || !R.teleporter_console) continue - if((T.z in config.admin_levels) || T.z > 7) + // TODO: Tie into space manager + if((T.z in config.admin_levels) || T.z > ZLEVEL_EMPTY) continue var/tmpname = T.loc.name if(areaindex[tmpname]) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 11b8b5c3d42..06b97e586fb 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -602,16 +602,13 @@ return -/obj/machinery/vending/proc/speak(var/message) +/obj/machinery/vending/proc/speak(message) if(stat & NOPOWER) return - if(!message) return - for(var/mob/O in hearers(src, null)) - O.show_message("[src] beeps, \"[message]\"",2) - return + atom_say(message) /obj/machinery/vending/power_change() if(stat & BROKEN) @@ -894,7 +891,7 @@ /obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 6,/obj/item/weapon/reagent_containers/syringe/insulin = 4, /obj/item/weapon/reagent_containers/syringe = 12,/obj/item/device/healthanalyzer = 5,/obj/item/device/healthupgrade = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2,/obj/item/stack/medical/bruise_pack/advanced = 3, /obj/item/stack/medical/ointment/advanced = 3, - /obj/item/stack/medical/bruise_pack = 3,/obj/item/stack/medical/splint = 2, /obj/item/device/sensor_device = 2) + /obj/item/stack/medical/bruise_pack = 3,/obj/item/stack/medical/splint = 4, /obj/item/device/sensor_device = 2) contraband = list(/obj/item/weapon/reagent_containers/glass/bottle/pancuronium = 1,/obj/item/weapon/reagent_containers/glass/bottle/sulfonal = 1) @@ -1232,7 +1229,7 @@ /obj/item/clothing/accessory/scarf/zebra=1,/obj/item/clothing/accessory/scarf/christmas=1,/obj/item/clothing/accessory/stripedredscarf=1, /obj/item/clothing/accessory/stripedbluescarf=1,/obj/item/clothing/accessory/stripedgreenscarf=1,/obj/item/clothing/accessory/waistcoat=1, /obj/item/clothing/under/sundress=2,/obj/item/clothing/under/stripeddress = 1, /obj/item/clothing/under/sailordress = 1, /obj/item/clothing/under/redeveninggown = 1, /obj/item/clothing/under/blacktango=1,/obj/item/clothing/suit/jacket=3, - /obj/item/clothing/glasses/regular=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1, + /obj/item/clothing/glasses/regular=2,/obj/item/clothing/glasses/sunglasses/fake=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1, /obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=2,/obj/item/clothing/shoes/black=4, /obj/item/clothing/shoes/sandal=1, /obj/item/clothing/gloves/fingerless=2, /obj/item/weapon/storage/belt/fannypack=1, /obj/item/weapon/storage/belt/fannypack/blue=1, /obj/item/weapon/storage/belt/fannypack/red=1) diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index 386afc0710c..b34897764e2 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -8,6 +8,7 @@ deflect_chance = 25 damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7) max_temperature = 60000 + burn_state = LAVA_PROOF infra_luminosity = 3 var/zoom = 0 var/thrusters = 0 diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index bef015cb7fa..cb55c783005 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -382,6 +382,7 @@ range = RANGED action(atom/target) + // TODO: Tie into space manager if(!action_checks(target) || (src.loc.z in config.admin_levels)) return var/turf/T = get_turf(target) if(T) @@ -403,6 +404,7 @@ action(atom/target) + // TODO: Tie into space manager if(!action_checks(target) || (src.loc.z in config.admin_levels)) return var/list/theareas = list() for(var/area/AR in orange(100, chassis)) @@ -1144,4 +1146,4 @@ if(do_after_cooldown(target)) new /obj/structure/barricade/mime/mrcd(target) chassis.spark_system.start() - chassis.use_power(energy_drain*2) \ No newline at end of file + chassis.use_power(energy_drain*2) diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index c4916306ac2..2a4f6adf189 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -68,6 +68,7 @@ initial_icon = "firefighter" max_temperature = 65000 health = 250 + burn_state = LAVA_PROOF lights_power = 7 damage_absorption = list("brute"=0.6,"fire"=0.5,"bullet"=0.7,"laser"=0.7,"energy"=1,"bomb"=0.4) max_equip = 5 // More armor, less tools diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index ada2399f20d..cead6e33ffd 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -49,6 +49,13 @@ M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src) return 1 +/obj/buckle_mob(mob/living/M) + . = ..() + if(.) + if(burn_state == ON_FIRE) //Sets the mob on fire if you buckle them to a burning atom/movableect + M.adjust_fire_stacks(1) + M.IgniteMob() + /atom/movable/proc/unbuckle_mob() if(buckled_mob && buckled_mob.buckled == src && buckled_mob.can_unbuckle(usr)) . = buckled_mob diff --git a/code/game/objects/effects/biomass_rift.dm b/code/game/objects/effects/biomass_rift.dm deleted file mode 100644 index 5b4cf9970a5..00000000000 --- a/code/game/objects/effects/biomass_rift.dm +++ /dev/null @@ -1,127 +0,0 @@ -/* -/obj/effect/biomass - icon = 'icons/obj/biomass.dmi' - icon_state = "stage1" - opacity = 0 - density = 0 - anchored = 1 - layer = 20 //DEBUG - plane = HUD_PLANE //DEBUG - var/health = 10 - var/stage = 1 - var/obj/effect/rift/originalRift = null //the originating rift of that biomass - var/maxDistance = 15 //the maximum length of a thread - var/newSpreadDistance = 10 //the length of a thread at which new ones are created - var/curDistance = 1 //the current length of a thread - var/continueChance = 3 //weighed chance of continuing in the same direction. turning left or right has 1 weight both - var/spreadDelay = 1 //will change to something bigger later, but right now I want it to spread as fast as possible for testing - -/obj/effect/rift - icon = 'icons/obj/biomass.dmi' - icon_state = "rift" - var/list/obj/effect/biomass/linkedBiomass = list() //all the biomass patches that have spread from it - var/newicon = 1 //DEBUG - -/obj/effect/rift/New() - set background = 1 - - ..() - - for(var/turf/T in orange(1,src)) - if(!IsValidBiomassLoc(T)) - continue - var/obj/effect/biomass/starting = new /obj/effect/biomass(T) - starting.dir = get_dir(src,starting) - starting.originalRift = src - linkedBiomass += starting - spawn(1) //DEBUG - starting.icon_state = "[newicon]" - -/obj/effect/rift/Del() - for(var/obj/effect/biomass/biomass in linkedBiomass) - del(biomass) - ..() - -/obj/effect/biomass/New() - set background = 1 - - ..() - if(!IsValidBiomassLoc(loc,src)) - del(src) - return - spawn(1) //so that the dir and stuff can be set by the source first - if(curDistance >= maxDistance) - return - switch(dir) - if(NORTHWEST) - dir = NORTH - if(NORTHEAST) - dir = EAST - if(SOUTHWEST) - dir = WEST - if(SOUTHEAST) - dir = SOUTH - sleep(spreadDelay) - Spread() - -/obj/effect/biomass/proc/Spread(var/direction = dir) - set background = 1 - var/possibleDirsInt = 0 - - for(var/newDirection in cardinal) - if(newDirection == turn(direction,180)) //can't go backwards - continue - var/turf/T = get_step(loc,newDirection) - if(!IsValidBiomassLoc(T,src)) - continue - possibleDirsInt |= newDirection - - var/list/possibleDirs = list() - - if(possibleDirsInt & direction) - for(var/i=0 , i 0) + spawn(lifespan) + qdel(src) /obj/effect/portal/Destroy() portals -= src @@ -33,6 +33,7 @@ var/obj/item/weapon/gun/energy/wormhole_projector/P = creator P.portal_destroyed(src) creator = null + target = null return ..() /obj/effect/portal/proc/teleport(atom/movable/M as mob|obj) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 111f7c4dc33..82412c8e883 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -192,6 +192,22 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d to_chat(user, "You try to move your [temp.name], but cannot!") return 0 + if(burn_state == ON_FIRE) + var/mob/living/carbon/human/H = user + if(istype(H)) + if(H.gloves && (H.gloves.max_heat_protection_temperature > 360)) + extinguish() + to_chat(user, "You put out the fire on [src].") + else + to_chat(user, "You burn your hand on [src]!") + var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_arm") + if(affecting && affecting.take_damage(0, 5)) // 5 burn damage + H.UpdateDamageIcon() + H.updatehealth() + return + else + extinguish() + if(istype(src.loc, /obj/item/weapon/storage)) //If the item is in a storage item, take it out var/obj/item/weapon/storage/S = src.loc diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index 9a46a843a56..f0c3ee84e98 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -1,81 +1,90 @@ /obj/item/candle name = "red candle" - desc = "a candle" + desc = "In Greek myth, Prometheus stole fire from the Gods and gave it to humankind. The jewelry he kept for himself." icon = 'icons/obj/candle.dmi' icon_state = "candle1" item_state = "candle1" w_class = 1 - - light_color = "#E09D37" - var/wax = 200 var/lit = 0 - proc - light(var/flavor_text = "\red [usr] lights the [name].") + var/infinite = 0 + var/start_lit = 0 + light_color = "#E09D37" + +/obj/item/candle/New() + ..() + if(start_lit) + // No visible message + light(show_message = 0) + +/obj/item/candle/update_icon() + var/i + if(wax>150) + i = 1 + else if(wax>80) + i = 2 + else i = 3 + icon_state = "candle[i][lit ? "_lit" : ""]" - update_icon() - var/i - if(wax>150) - i = 1 - else if(wax>80) - i = 2 - else i = 3 - icon_state = "candle[i][lit ? "_lit" : ""]" +/obj/item/candle/attackby(obj/item/weapon/W, mob/user, params) + ..() + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn()) //Badasses dont get blinded by lighting their candle with a welding tool + light("[user] casually lights [src] with [WT], what a badass.") + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.lit) + light("After some fiddling, [user] manages to light [src] with [L].") + else if(istype(W, /obj/item/weapon/match)) + var/obj/item/weapon/match/M = W + if(M.lit) + light("[user] lights [src] with [M]") + else if(istype(W, /obj/item/candle)) + var/obj/item/candle/C = W + if(C.lit) + light("[user] tilts [C] and lights [src] with it.") - attackby(obj/item/weapon/W as obj, mob/user as mob, params) - ..() - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn()) //Badasses dont get blinded by lighting their candle with a welding tool - light("\red [user] casually lights the [name] with [W], what a badass.") - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light() - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light() - else if(istype(W, /obj/item/candle)) - var/obj/item/candle/C = W - if(C.lit) - light() +/obj/item/candle/fire_act() + if(!lit) + light() //honk - - light(var/flavor_text = "\red [usr] lights the [name].") - if(!src.lit) - src.lit = 1 - //src.damtype = "fire" - for(var/mob/O in viewers(usr, null)) - O.show_message(flavor_text, 1) - set_light(CANDLE_LUM) - processing_objects.Add(src) - - - process() - if(!lit) - return - wax-- - if(!wax) - new/obj/item/trash/candle(src.loc) - if(istype(src.loc, /mob)) - var/mob/M = src.loc - M.unEquip(src, 1) //src is being deleted anyway - qdel(src) +/obj/item/candle/proc/light(show_message) + if(!lit) + lit = 1 + if(show_message) + usr.visible_message(show_message) + set_light(CANDLE_LUM) + processing_objects.Add(src) update_icon() - if(istype(loc, /turf)) //start a fire if possible - var/turf/T = loc - T.hotspot_expose(700, 5) - attack_self(mob/user as mob) - if(lit) - lit = 0 - update_icon() - set_light(0) +/obj/item/candle/process() + if(!lit) + return + if(!infinite) + wax-- + if(!wax) + new/obj/item/trash/candle(src.loc) + if(istype(src.loc, /mob)) + var/mob/M = src.loc + M.unEquip(src, 1) //src is being deleted anyway + qdel(src) + update_icon() + if(isturf(loc)) //start a fire if possible + var/turf/T = loc + T.hotspot_expose(700, 5) + + +/obj/item/candle/attack_self(mob/user) + if(lit) + user.visible_message("[user] snuffs out [src].") + lit = 0 + update_icon() + set_light(0) /obj/item/candle/eternal desc = "A candle. This one seems to have an odd quality about the wax." - wax = 10000 \ No newline at end of file + infinite = 1 \ No newline at end of file diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm index 178f56912c1..4c2c5420d1a 100644 --- a/code/game/objects/items/control_wand.dm +++ b/code/game/objects/items/control_wand.dm @@ -18,6 +18,12 @@ ID = new /obj/item/weapon/card/id ID.access = get_region_accesses(region_access) +/obj/item/weapon/door_remote/Destroy() + if(ID) + qdel(ID) + ID = null + return ..() + /obj/item/weapon/door_remote/attack_self(mob/user) switch(mode) if(WAND_OPEN) diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index 974835b6a2d..dec4f4c75fb 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -61,6 +61,7 @@ return null var/turf/T = get_turf(user.loc) + // TODO: Tie into space manager if(T.z != current.z || !current.can_use()) to_chat(user, "[src] has lost the signal.") current = null @@ -225,6 +226,7 @@ to_chat(usr, "Something's wrong with that camera. You can't get a feed.") return var/turf/T = get_turf(loc) + // TODO: Tie into space manager if(!T || C.z != T.z) to_chat(usr, "You can't get a signal.") return @@ -284,4 +286,4 @@ #undef BUGMODE_LIST #undef BUGMODE_MONITOR -#undef BUGMODE_TRACK \ No newline at end of file +#undef BUGMODE_TRACK diff --git a/code/game/objects/items/devices/guitar.dm b/code/game/objects/items/devices/guitar.dm index dc9067c34e4..b95cea0aae3 100644 --- a/code/game/objects/items/devices/guitar.dm +++ b/code/game/objects/items/devices/guitar.dm @@ -7,6 +7,8 @@ icon_state = "guitar" item_state = "guitar" force = 10 + burn_state = FLAMMABLE + burntime = 20 var/datum/song/handheld/song hitsound = 'sound/effects/guitarsmash.ogg' diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 0996fdd6de5..18aff184931 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -11,7 +11,6 @@ w_class = 2 //Increased to 2, because diodes are w_class 2. Conservation of matter. origin_tech = "combat=1" origin_tech = "magnets=2" - var/turf/pointer_loc var/energy = 5 var/max_energy = 5 var/effectchance = 33 @@ -35,6 +34,12 @@ if(!pointer_icon_state) pointer_icon_state = pick("red_laser","green_laser","blue_laser","purple_laser") +/obj/item/device/laser_pointer/Destroy() + if(diode) + qdel(diode) + diode = null + return ..() + /obj/item/device/laser_pointer/upgraded/New() ..() diode = new /obj/item/weapon/stock_parts/micro_laser/ultra diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 893ce504319..f6f39504390 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -24,9 +24,13 @@ overlays += "pai-off" /obj/item/device/paicard/Destroy() - //Will stop people throwing friend pAIs into the singularity so they can respawn - if(!isnull(pai)) - pai.death(0) + if(pai) + pai.ghostize() + qdel(pai) + pai = null + if(radio) + qdel(radio) + radio = null return ..() /obj/item/device/paicard/attack_self(mob/user) diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 455a0f7098c..a8623b17f56 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -124,6 +124,7 @@ return -1 if(!(0 in level)) var/turf/position = get_turf(src) + // TODO: Tie into space manager if(isnull(position) || !(position.z in level)) return -1 if(!src.listening) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 9ea2f17378a..d804c874e1a 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -20,6 +20,12 @@ mytape = new /obj/item/device/tape/random(src) update_icon() +/obj/item/device/taperecorder/Destroy() + if(mytape) + qdel(mytape) + mytape = null + return ..() + /obj/item/device/taperecorder/examine(mob/user) if(..(user, 1)) to_chat(user, "The wire panel is [open_panel ? "opened" : "closed"].") @@ -42,6 +48,10 @@ update_icon() +/obj/item/device/taperecorder/fire_act() + mytape.ruin() //Fires destroy the tape + return ..() + /obj/item/device/taperecorder/attack_hand(mob/user) if(loc == user) if(mytape) @@ -253,6 +263,8 @@ var/list/timestamp = list() var/ruined = 0 +/obj/item/device/tape/fire_act() + ruin() /obj/item/device/tape/attack_self(mob/user) if(!ruined) @@ -277,7 +289,8 @@ timestamp.Cut() /obj/item/device/tape/proc/ruin() - overlays += "ribbonoverlay" + if(!ruined) + overlays += "ribbonoverlay" ruined = 1 diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 8e8e00a0343..9cd39c7a7d9 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -11,6 +11,18 @@ var/toggle = 1 origin_tech = "materials=1;engineering=1" +/obj/item/device/transfer_valve/Destroy() + if(tank_one) + qdel(tank_one) + tank_one = null + if(tank_two) + qdel(tank_two) + tank_two = null + if(attached_device) + qdel(attached_device) + attached_device = null + return ..() + /obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D) /obj/item/device/transfer_valve/IsAssemblyHolder() diff --git a/code/game/objects/items/devices/violin.dm b/code/game/objects/items/devices/violin.dm index 9c4d5e9ddb4..c0cc320fdc3 100644 --- a/code/game/objects/items/devices/violin.dm +++ b/code/game/objects/items/devices/violin.dm @@ -7,6 +7,8 @@ icon_state = "violin" item_state = "violin" force = 10 + burn_state = FLAMMABLE + burntime = 20 hitsound = 'sound/weapons/smash.ogg' var/datum/song/handheld/song @@ -18,7 +20,7 @@ qdel(song) song = null return ..() - + /obj/item/device/violin/initialize() song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded ..() diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm index 879a6846639..ea018289e0f 100644 --- a/code/game/objects/items/flag.dm +++ b/code/game/objects/items/flag.dm @@ -1,77 +1,14 @@ /obj/item/flag icon = 'icons/obj/flag.dmi' w_class = 4 - var/lit = 0 - var/burntime = 30 + burntime = 20 + burn_state = FLAMMABLE -/obj/item/flag/fire_act(null, temperature, volume) - if(!lit) - Ignite() - return - -/obj/item/flag/proc/Ignite() - if(lit) return - lit = 1 - update_icons() - processing_objects.Add(src) - -/obj/item/flag/process() - burntime-- - if(burntime < 1) - processing_objects.Remove(src) - if(istype(src.loc,/turf)) - new /obj/effect/decal/cleanable/ash(src.loc) - new /obj/item/stack/rods(src.loc) - qdel(src) - return - if(istype(src.loc,/mob/living/carbon)) - var/mob/living/carbon/C = src.loc - var/turf/location = get_turf(C) - new /obj/effect/decal/cleanable/ash(location) - new /obj/item/stack/rods(location) - qdel(src) - return - else - qdel(src) - return - -/obj/item/flag/attackby(obj/item/weapon/W as obj, mob/user as mob, params) +/obj/item/flag/attackby(obj/item/weapon/W, mob/user, params) ..() - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn())//Badasses dont get blinded while lighting their cig with a welding tool - light("[user] casually lights the [name] with [W], what a badass.") - - else if(istype(W, /obj/item/weapon/lighter/zippo)) - var/obj/item/weapon/lighter/zippo/Z = W - if(Z.lit) - light("With a single flick of their wrist, [user] smoothly lights the [name] with their [W]. Damn they're cool.") - - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light("After some fiddling, [user] manages to light the [name] with [W].") - - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light("[user] lights the [name] with their [W].") - - else if(istype(W, /obj/item/weapon/melee/energy/sword/saber)) - var/obj/item/weapon/melee/energy/sword/saber/S = W - if(S.active) - light("[user] swings their [W], barely missing their nose. They light the [name] in the process.") - - else if(istype(W, /obj/item/device/assembly/igniter)) - light("[user] fiddles with [W], and manages to light the [name].") - -/obj/item/flag/proc/light(var/flavor_text = "[usr] lights the [name].") - if(!src.lit) - src.lit = 1 - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - update_icons() - processing_objects.Add(src) + if(is_hot(W) && burn_state != ON_FIRE) + user.visible_message("[user] lights the [name] with [W].") + fire_act() /obj/item/flag/proc/update_icons() overlays = null diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index 575680f28ac..855c97d9b12 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -11,6 +11,12 @@ var/state var/datum/gas_mixture/air_contents = null +/obj/item/latexballon/Destroy() + if(air_contents) + qdel(air_contents) + air_contents = null + return ..() + /obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank, mob/user) if(icon_state == "latexballon_bursted") return diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index c34710d01f0..2c6d04b9c06 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -2,16 +2,18 @@ name = "medical pack" singular_name = "medical pack" icon = 'icons/obj/items.dmi' - amount = 5 - max_amount = 5 + amount = 6 + max_amount = 6 w_class = 1 throw_speed = 3 throw_range = 7 var/heal_brute = 0 var/heal_burn = 0 + var/self_delay = 20 + var/unique_handling = 0 //some things give a special prompt, do we want to bypass some checks in parent? -/obj/item/stack/medical/attack(mob/living/carbon/M, mob/user) - if(!istype(M)) +/obj/item/stack/medical/attack(mob/living/M, mob/user) + if(!iscarbon(M) && !isanimal(M)) to_chat(user, "[src] cannot be applied to [M]!") return 1 @@ -20,13 +22,12 @@ return 1 - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - if(isliving(M)) - if(!M.can_inject(user, 1)) - return 1 + if(!H.can_inject(user, 1)) + return 1 if(!affecting) to_chat(user, "That limb is missing!") @@ -36,16 +37,36 @@ to_chat(user, "This can't be used on a robotic limb.") return 1 + if(M == user && !unique_handling) + user.visible_message("[user] starts to apply [src] on [H]...") + if(!do_mob(user, H, self_delay)) + return 1 + return - H.UpdateDamageIcon() + if(isanimal(M)) + var/mob/living/simple_animal/critter = M + if(!(critter.healable)) + to_chat(user, "You cannot use [src] on [critter]!") + return + else if (critter.health == critter.maxHealth) + to_chat(user, "[critter] is at full health.") + return + else if(heal_brute < 1) + to_chat(user, "[src] won't help [critter] at all.") + return + + critter.heal_organ_damage(heal_brute, heal_burn) + user.visible_message("[user] applies [src] on [critter].", \ + "You apply [src] on [critter].") - else - M.heal_organ_damage(heal_brute/2, heal_burn/2) - user.visible_message("[M] has been applied with [src] by [user].", \ - "You apply [src] to [M].") use(1) - M.updatehealth() + else + M.heal_organ_damage(heal_brute, heal_burn) + M.updatehealth() + user.visible_message("[user] applies [src] on [M].", \ + "You apply [src] on [M].") + use(1) //Bruise Packs// @@ -56,11 +77,11 @@ icon_state = "gauze" origin_tech = "biotech=1" -/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M, mob/user) +/obj/item/stack/medical/bruise_pack/attack(mob/living/M, mob/user) if(..()) return 1 - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) @@ -69,26 +90,17 @@ var/disinfected = affecting.disinfect() if(!(bandaged || disinfected)) - to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") + to_chat(user, "The wounds on [H]'s [affecting.name] have already been bandaged.") return 1 else - for(var/datum/wound/W in affecting.wounds) - if(W.internal) - continue - if(W.current_stage <= W.max_bleeding_stage) - user.visible_message("[user] bandages \the [W.desc] on [M]'s [affecting.name].", \ - "You bandage \the [W.desc] on [M]'s [affecting.name]." ) - else if(istype(W,/datum/wound/bruise)) - user.visible_message("[user] places a bruise patch over \the [W.desc] on [M]'s [affecting.name].", \ - "You place a bruise patch over \the [W.desc] on [M]'s [affecting.name]." ) - else - user.visible_message("[user] places a bandaid over \the [W.desc] on [M]'s [affecting.name].", \ - "You place a bandaid over \the [W.desc] on [M]'s [affecting.name]." ) - if(bandaged) - affecting.heal_damage(heal_brute, heal_burn) + user.visible_message("[user] bandages the wounds on [H]'s [affecting.name].", \ + "You bandage the wounds on [H]'s [affecting.name]." ) + + affecting.heal_damage(heal_brute, heal_burn) + H.UpdateDamageIcon() use(1) else - to_chat(user, "[affecting] is cut open, you'll need more than a bandage!") + to_chat(user, "[affecting] is cut open, you'll need more than a bandage!") /obj/item/stack/medical/bruise_pack/advanced @@ -96,7 +108,7 @@ singular_name = "advanced trauma kit" desc = "An advanced trauma kit for severe injuries." icon_state = "traumakit" - heal_brute = 12 + heal_brute = 25 @@ -111,25 +123,26 @@ icon_state = "ointment" origin_tech = "biotech=1" -/obj/item/stack/medical/ointment/attack(mob/living/carbon/M, mob/user) +/obj/item/stack/medical/ointment/attack(mob/living/M, mob/user) if(..()) return 1 - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open == 0) if(!affecting.salve()) - to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") + to_chat(user, "The wounds on [H]'s [affecting.name] have already been salved.") return 1 else - user.visible_message("[user] salves the wounds on [M]'s [affecting.name].", \ - "You salve the wounds on [M]'s [affecting.name]." ) + user.visible_message("[user] salves the wounds on [H]'s [affecting.name].", \ + "You salve the wounds on [H]'s [affecting.name]." ) affecting.heal_damage(heal_brute, heal_burn) + H.UpdateDamageIcon() use(1) else - to_chat(user, "[affecting] is cut open, you'll need more than some ointment!") + to_chat(user, "[affecting] is cut open, you'll need more than some ointment!") /obj/item/stack/medical/ointment/advanced @@ -137,7 +150,7 @@ singular_name = "advanced burn kit" desc = "An advanced treatment kit for severe burns." icon_state = "burnkit" - heal_burn = 12 + heal_burn = 25 @@ -151,7 +164,7 @@ icon = 'icons/obj/hydroponics_products.dmi' icon_state = "alien3-product" color = "#378C61" - heal_brute = 7 + heal_brute = 12 /obj/item/stack/medical/ointment/aloe @@ -161,7 +174,7 @@ icon = 'icons/obj/hydroponics_products.dmi' icon_state = "ambrosia-product" color = "#4CC5C7" - heal_burn = 7 + heal_burn = 12 @@ -172,14 +185,14 @@ name = "medical splints" singular_name = "medical splint" icon_state = "splint" - amount = 5 - max_amount = 5 + unique_handling = 1 + self_delay = 100 -/obj/item/stack/medical/splint/attack(mob/living/carbon/M, mob/user) +/obj/item/stack/medical/splint/attack(mob/living/M, mob/user) if(..()) return 1 - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) var/limb = affecting.name @@ -187,36 +200,21 @@ to_chat(user, "You can't apply a splint there!") return if(affecting.status & ORGAN_SPLINTED) - to_chat(user, "[M]'s [limb] is already splinted!") - if(alert(user, "Would you like to remove the splint from [M]'s [limb]?", "Removing.", "Yes", "No") == "Yes") + to_chat(user, "[H]'s [limb] is already splinted!") + if(alert(user, "Would you like to remove the splint from [H]'s [limb]?", "Removing.", "Yes", "No") == "Yes") affecting.status &= ~ORGAN_SPLINTED - to_chat(user, "You remove the splint from [M]'s [limb].") + to_chat(user, "You remove the splint from [H]'s [limb].") return - if(M != user) - user.visible_message("[user] starts to apply [src] to [M]'s [limb].", \ - "You start to apply [src] to [M]'s [limb].", \ + if(M == user) + user.visible_message("[user] starts to apply [src] to [H]'s [limb].", \ + "You start to apply [src] to [H]'s [limb].", \ "You hear something being wrapped.") - else - if((!user.hand && affecting.limb_name in list("r_arm", "r_hand")) || (user.hand && affecting.limb_name in list("l_arm", "l_hand"))) - to_chat(user, "You can't apply a splint to the arm you're using!") + if(!do_mob(user, H, self_delay)) return - user.visible_message("[user] starts to apply [src] to their [limb].", \ - "You start to apply [src] to your [limb].", \ - "You hear something being wrapped.") - if(do_after(user, 50, target = M)) - if(M != user) - user.visible_message("[user] finishes applying [src] to [M]'s [limb].", \ - "You finish applying [src] to [M]'s [limb].", \ - "You hear something being wrapped.") - else - if(prob(25)) - user.visible_message("[user] successfully applies [src] to their [limb].", \ - "You successfully apply [src] to your [limb].", \ - "You hear something being wrapped.") - else - user.visible_message("[user] fumbles [src].", - "You fumble [src].", - "You hear something being wrapped.") - return - affecting.status |= ORGAN_SPLINTED - use(1) + else + user.visible_message("[user] applies [src] to their [limb].", \ + "You apply [src] to your [limb].", \ + "You hear something being wrapped.") + + affecting.status |= ORGAN_SPLINTED + use(1) diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm index f96b10fff23..4d8b27a6690 100644 --- a/code/game/objects/items/stacks/sheets/light.dm +++ b/code/game/objects/items/stacks/sheets/light.dm @@ -21,16 +21,16 @@ new/obj/item/stack/sheet/glass(user.loc) if(amount <= 0) user.unEquip(src, 1) - del(src) + qdel(src) if(istype(O,/obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = O M.amount-- if(M.amount <= 0) user.unEquip(src, 1) - del(M) + qdel(M) amount-- new/obj/item/stack/tile/light(user.loc) if(amount <= 0) user.unEquip(src, 1) - del(src) + qdel(src) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 55fda54267f..f509f74d79b 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -125,11 +125,25 @@ var/global/list/datum/stack_recipe/mime_recipes = list ( \ origin_tech = "plasmatech=2;materials=2" sheettype = "plasma" materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT) + burn_state = FLAMMABLE + burntime = 5 /obj/item/stack/sheet/mineral/plasma/New() ..() recipes = plasma_recipes +/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/weapon/W, mob/user, params) + if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite + message_admins("Plasma sheets ignited by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)",0,1) + log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])") + fire_act() + else + return ..() + +/obj/item/stack/sheet/mineral/plasma/fire_act() + atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, amount*10) + qdel(src) + /obj/item/stack/sheet/mineral/plastic name = "Plastic" icon_state = "sheet-plastic" diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 98fa7a955ab..0b99edde497 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -10,80 +10,82 @@ /* * Metal */ -var/global/list/datum/stack_recipe/metal_recipes = list ( \ - new/datum/stack_recipe("stool", /obj/structure/stool, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("chair", /obj/structure/stool/bed/chair, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("sofa (middle)", /obj/structure/stool/bed/chair/sofa, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("sofa (left)", /obj/structure/stool/bed/chair/sofa/left, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("sofa (right)", /obj/structure/stool/bed/chair/sofa/right, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("sofa (corner)", /obj/structure/stool/bed/chair/sofa/corner, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("barber chair", /obj/structure/stool/bed/chair/barber, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("wheelchair", /obj/structure/stool/bed/chair/wheelchair, 15, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("bed", /obj/structure/stool/bed, 2, one_per_turf = 1, on_floor = 1), \ - null, \ - new/datum/stack_recipe_list("office chairs",list( \ - new/datum/stack_recipe("dark office chair", /obj/structure/stool/bed/chair/office/dark, 5, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("light office chair", /obj/structure/stool/bed/chair/office/light, 5, one_per_turf = 1, on_floor = 1), \ - ), 5), \ - new/datum/stack_recipe_list("comfy chairs", list( \ - new/datum/stack_recipe("beige comfy chair", /obj/structure/stool/bed/chair/comfy/beige, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("black comfy chair", /obj/structure/stool/bed/chair/comfy/black, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("brown comfy chair", /obj/structure/stool/bed/chair/comfy/brown, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("lime comfy chair", /obj/structure/stool/bed/chair/comfy/lime, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("teal comfy chair", /obj/structure/stool/bed/chair/comfy/teal, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("red comfy chair", /obj/structure/stool/bed/chair/comfy/red, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("blue comfy chair", /obj/structure/stool/bed/chair/comfy/blue, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("purple comfy chair", /obj/structure/stool/bed/chair/comfy/purp, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("green comfy chair", /obj/structure/stool/bed/chair/comfy/green, 2, one_per_turf = 1, on_floor = 1), \ - ), 2), \ - null, \ - new/datum/stack_recipe("table parts", /obj/item/weapon/table_parts, 2), \ - new/datum/stack_recipe("glass table frame parts", /obj/item/weapon/table_parts/glass, 2), \ - new/datum/stack_recipe("rack parts", /obj/item/weapon/rack_parts), \ - new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = 1, on_floor = 1), \ - null, \ - new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1), \ - null, \ - new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \ - new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \ - null, \ - new/datum/stack_recipe("computer frame", /obj/structure/computerframe, 5, time = 25, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("machine frame", /obj/machinery/constructable_frame/machine_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("meatspike frame", /obj/structure/kitchenspike_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), \ - null, \ - new/datum/stack_recipe_list("airlock assemblies", list( \ - new/datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("security airlock assembly", /obj/structure/door_assembly/door_assembly_sec, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("engineering airlock assembly", /obj/structure/door_assembly/door_assembly_eng, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("mining airlock assembly", /obj/structure/door_assembly/door_assembly_min, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("atmospherics airlock assembly", /obj/structure/door_assembly/door_assembly_atmo, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("research airlock assembly", /obj/structure/door_assembly/door_assembly_research, 4, time = 50, one_per_turf = 1, on_floor = 1), \ -/* new/datum/stack_recipe("science airlock assembly", /obj/structure/door_assembly/door_assembly_science, 4, time = 50, one_per_turf = 1, on_floor = 1), \ */ - new/datum/stack_recipe("medical airlock assembly", /obj/structure/door_assembly/door_assembly_med, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("freezer airlock assembly", /obj/structure/door_assembly/door_assembly_fre, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, 4, time = 50, one_per_turf = 1, on_floor = 1), \ - ), 4), \ - null, \ - new/datum/stack_recipe("mass driver button frame", /obj/item/mounted/frame/driver_button, 1, time = 50, one_per_turf = 0, on_floor = 1), \ - new/datum/stack_recipe("light switch frame", /obj/item/mounted/frame/light_switch, 1, time = 50, one_per_turf = 0, on_floor = 1), \ - null, \ - new/datum/stack_recipe("grenade casing", /obj/item/weapon/grenade/chem_grenade), \ - new/datum/stack_recipe("light fixture frame", /obj/item/mounted/frame/light_fixture, 2), \ - new/datum/stack_recipe("small light fixture frame", /obj/item/mounted/frame/light_fixture/small, 1), \ - null, \ - new/datum/stack_recipe("apc frame", /obj/item/mounted/frame/apc_frame, 2), \ - new/datum/stack_recipe("air alarm frame", /obj/item/mounted/frame/alarm_frame, 2), \ - new/datum/stack_recipe("fire alarm frame", /obj/item/mounted/frame/firealarm, 2), \ - new/datum/stack_recipe("intercom frame", /obj/item/mounted/frame/intercom, 2), \ - null, \ +var/global/list/datum/stack_recipe/metal_recipes = list( + new /datum/stack_recipe("stool", /obj/structure/stool, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("chair", /obj/structure/stool/bed/chair, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("sofa (middle)", /obj/structure/stool/bed/chair/sofa, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("sofa (left)", /obj/structure/stool/bed/chair/sofa/left, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("sofa (right)", /obj/structure/stool/bed/chair/sofa/right, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("sofa (corner)", /obj/structure/stool/bed/chair/sofa/corner, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("barber chair", /obj/structure/stool/bed/chair/barber, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("wheelchair", /obj/structure/stool/bed/chair/wheelchair, 15, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("bed", /obj/structure/stool/bed, 2, one_per_turf = 1, on_floor = 1), + null, + new /datum/stack_recipe_list("office chairs",list( + new /datum/stack_recipe("dark office chair", /obj/structure/stool/bed/chair/office/dark, 5, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("light office chair", /obj/structure/stool/bed/chair/office/light, 5, one_per_turf = 1, on_floor = 1), + ), 5), + + new /datum/stack_recipe_list("comfy chairs", list( + new /datum/stack_recipe("beige comfy chair", /obj/structure/stool/bed/chair/comfy/beige, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("black comfy chair", /obj/structure/stool/bed/chair/comfy/black, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("brown comfy chair", /obj/structure/stool/bed/chair/comfy/brown, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("lime comfy chair", /obj/structure/stool/bed/chair/comfy/lime, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("teal comfy chair", /obj/structure/stool/bed/chair/comfy/teal, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("red comfy chair", /obj/structure/stool/bed/chair/comfy/red, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("blue comfy chair", /obj/structure/stool/bed/chair/comfy/blue, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("purple comfy chair", /obj/structure/stool/bed/chair/comfy/purp, 2, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("green comfy chair", /obj/structure/stool/bed/chair/comfy/green, 2, one_per_turf = 1, on_floor = 1), + ), 2), + + null, + new /datum/stack_recipe("table parts", /obj/item/weapon/table_parts, 2), + new /datum/stack_recipe("glass table frame parts", /obj/item/weapon/table_parts/glass, 2), + new /datum/stack_recipe("rack parts", /obj/item/weapon/rack_parts), + new /datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = 1, on_floor = 1), + null, + new /datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1), + null, + new /datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), + new /datum/stack_recipe/rods("metal rod", /obj/item/stack/rods, 1, 2, 60), + null, + new /datum/stack_recipe("computer frame", /obj/structure/computerframe, 5, time = 25, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("machine frame", /obj/machinery/constructable_frame/machine_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("meatspike frame", /obj/structure/kitchenspike_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), + null, + new /datum/stack_recipe_list("airlock assemblies", list( + new /datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("security airlock assembly", /obj/structure/door_assembly/door_assembly_sec, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("engineering airlock assembly", /obj/structure/door_assembly/door_assembly_eng, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("mining airlock assembly", /obj/structure/door_assembly/door_assembly_min, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("atmospherics airlock assembly", /obj/structure/door_assembly/door_assembly_atmo, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("research airlock assembly", /obj/structure/door_assembly/door_assembly_research, 4, time = 50, one_per_turf = 1, on_floor = 1), +/* new /datum/stack_recipe("science airlock assembly", /obj/structure/door_assembly/door_assembly_science, 4, time = 50, one_per_turf = 1, on_floor = 1), */ + new /datum/stack_recipe("medical airlock assembly", /obj/structure/door_assembly/door_assembly_med, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("freezer airlock assembly", /obj/structure/door_assembly/door_assembly_fre, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, 4, time = 50, one_per_turf = 1, on_floor = 1), + ), 4), + null, + new /datum/stack_recipe("mass driver button frame", /obj/item/mounted/frame/driver_button, 1, time = 50, one_per_turf = 0, on_floor = 1), + new /datum/stack_recipe("light switch frame", /obj/item/mounted/frame/light_switch, 1, time = 50, one_per_turf = 0, on_floor = 1), + null, + new /datum/stack_recipe("grenade casing", /obj/item/weapon/grenade/chem_grenade), + new /datum/stack_recipe("light fixture frame", /obj/item/mounted/frame/light_fixture, 2), + new /datum/stack_recipe("small light fixture frame", /obj/item/mounted/frame/light_fixture/small, 1), + null, + new /datum/stack_recipe("apc frame", /obj/item/mounted/frame/apc_frame, 2), + new /datum/stack_recipe("air alarm frame", /obj/item/mounted/frame/alarm_frame, 2), + new /datum/stack_recipe("fire alarm frame", /obj/item/mounted/frame/firealarm, 2), + new /datum/stack_recipe("intercom frame", /obj/item/mounted/frame/intercom, 2), + null ) /obj/item/stack/sheet/metal @@ -106,13 +108,12 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \ /* * Plasteel */ -var/global/list/datum/stack_recipe/plasteel_recipes = list ( \ - new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1), \ - new/datum/stack_recipe("Surgery Table", /obj/machinery/optable, 5, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1), \ - new/datum/stack_recipe("Mass Driver frame", /obj/machinery/mass_driver_frame, 3, time = 50, one_per_turf = 1), \ - - ) +var/global/list/datum/stack_recipe/plasteel_recipes = list( + new /datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1), + new /datum/stack_recipe("Surgery Table", /obj/machinery/optable, 5, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1), + new /datum/stack_recipe("Mass Driver frame", /obj/machinery/mass_driver_frame, 3, time = 50, one_per_turf = 1) +) /obj/item/stack/sheet/plasteel name = "plasteel" @@ -132,21 +133,21 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list ( \ /* * Wood */ -var/global/list/datum/stack_recipe/wood_recipes = list ( \ - new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \ - new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \ - new/datum/stack_recipe("table parts", /obj/item/weapon/table_parts/wood, 2), \ - new/datum/stack_recipe("wooden chair", /obj/structure/stool/bed/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("bookcase", /obj/structure/bookcase, 5, time = 50, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \ - new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("easel", /obj/structure/easel, 3, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("wooden buckler", /obj/item/weapon/shield/riot/buckler, 20, time = 40), \ - new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\ - new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\ - ) +var/global/list/datum/stack_recipe/wood_recipes = list( + new /datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), + new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), + new /datum/stack_recipe("table parts", /obj/item/weapon/table_parts/wood, 2), + new /datum/stack_recipe("wooden chair", /obj/structure/stool/bed/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("bookcase", /obj/structure/bookcase, 5, time = 50, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), + new /datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("easel", /obj/structure/easel, 3, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("wooden buckler", /obj/item/weapon/shield/riot/buckler, 20, time = 40), + new /datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50), + new /datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10) +) /obj/item/stack/sheet/wood name = "wooden planks" @@ -155,6 +156,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ singular_name = "wood plank" icon_state = "sheet-wood" origin_tech = "materials=1;biotech=1" + burn_state = FLAMMABLE /obj/item/stack/sheet/wood/New(var/loc, var/amount=null) recipes = wood_recipes @@ -169,22 +171,23 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ singular_name = "cloth roll" icon_state = "sheet-cloth" origin_tech = "materials=2" + burn_state = FLAMMABLE /* * Cardboard */ -var/global/list/datum/stack_recipe/cardboard_recipes = list ( \ - new/datum/stack_recipe("box", /obj/item/weapon/storage/box), \ - new/datum/stack_recipe("large box", /obj/item/weapon/storage/box/large, 4), \ - new/datum/stack_recipe("light tubes", /obj/item/weapon/storage/box/lights/tubes), \ - new/datum/stack_recipe("light bulbs", /obj/item/weapon/storage/box/lights/bulbs), \ - new/datum/stack_recipe("mouse traps", /obj/item/weapon/storage/box/mousetraps), \ - new/datum/stack_recipe("cardborg suit", /obj/item/clothing/suit/cardborg, 3), \ - new/datum/stack_recipe("cardborg helmet", /obj/item/clothing/head/cardborg), \ - new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \ - new/datum/stack_recipe("folder", /obj/item/weapon/folder), \ - new/datum/stack_recipe("cardboard tube", /obj/item/weapon/c_tube), \ - new/datum/stack_recipe("cardboard box", /obj/structure/closet/cardboard, 4), \ +var/global/list/datum/stack_recipe/cardboard_recipes = list ( + new /datum/stack_recipe("box", /obj/item/weapon/storage/box), + new /datum/stack_recipe("large box", /obj/item/weapon/storage/box/large, 4), + new /datum/stack_recipe("light tubes", /obj/item/weapon/storage/box/lights/tubes), + new /datum/stack_recipe("light bulbs", /obj/item/weapon/storage/box/lights/bulbs), + new /datum/stack_recipe("mouse traps", /obj/item/weapon/storage/box/mousetraps), + new /datum/stack_recipe("cardborg suit", /obj/item/clothing/suit/cardborg, 3), + new /datum/stack_recipe("cardborg helmet", /obj/item/clothing/head/cardborg), + new /datum/stack_recipe("pizza box", /obj/item/pizzabox), + new /datum/stack_recipe("folder", /obj/item/weapon/folder), + new /datum/stack_recipe("cardboard tube", /obj/item/weapon/c_tube), + new /datum/stack_recipe("cardboard box", /obj/structure/closet/cardboard, 4), ) /obj/item/stack/sheet/cardboard //BubbleWrap @@ -193,7 +196,8 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list ( \ singular_name = "cardboard sheet" icon_state = "sheet-card" origin_tech = "materials=1" + burn_state = FLAMMABLE -/obj/item/stack/sheet/cardboard/New(var/loc, var/amount=null) - recipes = cardboard_recipes - return ..() +/obj/item/stack/sheet/cardboard/New(var/loc, var/amt = null) + recipes = cardboard_recipes + return ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 5b78e8587d9..753cc9f9de8 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -10,156 +10,172 @@ */ /obj/item/stack origin_tech = "materials=1" - var/list/datum/stack_recipe/recipes + var/list/recipes = list() // /datum/stack_recipe var/singular_name var/amount = 1 var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount -/obj/item/stack/New(var/loc, var/amount=null) +/obj/item/stack/New(var/loc, var/amt = null) ..() - if(amount!=null) //Allow for stacks with the amount=0 - src.amount=amount - return + if(amt != null) //Allow for stacks with the amount=0 + amount = amt /obj/item/stack/Destroy() - if(usr && usr.machine==src) + if(usr && usr.machine == src) usr << browse(null, "window=stack") - return ..() + ..() + return QDEL_HINT_HARDDEL_NOW // because qdel'd stacks act strange for cyborgs /obj/item/stack/examine(mob/user) if(..(user, 1)) - to_chat(user, "There are [src.amount] [src.singular_name]\s in the stack.") + to_chat(user, "There are [amount] [singular_name]\s in the stack.") - -/obj/item/stack/attack_self(mob/user as mob) +/obj/item/stack/attack_self(mob/user) list_recipes(user) -/obj/item/stack/proc/list_recipes(mob/user as mob, recipes_sublist) +/obj/item/stack/proc/list_recipes(mob/user, recipes_sublist) if(!recipes) return - if(!src || amount<=0) + + if(amount <= 0) user << browse(null, "window=stack") + return + user.set_machine(src) //for correct work of onclose + var/list/recipe_list = recipes if(recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list)) var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist] recipe_list = srl.recipes + var/t1 = "Amount Left: [amount]
    " - for(var/i=1;i<=recipe_list.len,i++) + for(var/i in 1 to recipe_list.len) var/E = recipe_list[i] if(isnull(E)) t1 += "
    " continue - if(i>1 && !isnull(recipe_list[i-1])) - t1+="
    " + if(i > 1 && !isnull(recipe_list[i - 1])) + t1 += "
    " if(istype(E, /datum/stack_recipe_list)) var/datum/stack_recipe_list/srl = E - if(src.amount >= srl.req_amount) - t1 += "[srl.title] ([srl.req_amount] [src.singular_name]\s)" + if(amount >= srl.req_amount) + t1 += "[srl.title] ([srl.req_amount] [singular_name]\s)" else - t1 += "[srl.title] ([srl.req_amount] [src.singular_name]\s)
    " + t1 += "[srl.title] ([srl.req_amount] [singular_name]\s)
    " if(istype(E, /datum/stack_recipe)) var/datum/stack_recipe/R = E var/max_multiplier = round(src.amount / R.req_amount) - var/title as text + var/title var/can_build = 1 - can_build = can_build && (max_multiplier>0) + can_build = can_build && (max_multiplier > 0) /* if(R.one_per_turf) can_build = can_build && !(locate(R.result_type) in usr.loc) if(R.on_floor) can_build = can_build && istype(usr.loc, /turf/simulated/floor) */ - if(R.res_amount>1) - title+= "[R.res_amount]x [R.title]\s" + if(R.res_amount > 1) + title += "[R.res_amount]x [R.title]\s" else - title+= "[R.title]" - title+= " ([R.req_amount] [src.singular_name]\s)" + title += "[R.title]" + title += " ([R.req_amount] [src.singular_name]\s)" if(can_build) - t1 += text("[title] ") + t1 += "[title] " else - t1 += text("[]", title) + t1 += "[title]" continue if(R.max_res_amount>1 && max_multiplier>1) - max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount)) + max_multiplier = min(max_multiplier, round(R.max_res_amount / R.res_amount)) t1 += " |" var/list/multipliers = list(5,10,25) for(var/n in multipliers) if(max_multiplier>=n) - t1 += " [n*R.res_amount]x" + t1 += " [n * R.res_amount]x" if(!(max_multiplier in multipliers)) - t1 += " [max_multiplier*R.res_amount]x" + t1 += " [max_multiplier * R.res_amount]x" var/datum/browser/popup = new(user, "stack", name, 400, 400) popup.set_content(t1) popup.open(0) onclose(user, "stack") - return /obj/item/stack/Topic(href, href_list) ..() - if((usr.restrained() || usr.stat || usr.get_active_hand() != src)) - return + if(usr.incapacitated() || usr.get_active_hand() != src) + return 0 if(href_list["sublist"] && !href_list["make"]) list_recipes(usr, text2num(href_list["sublist"])) if(href_list["make"]) - if(src.amount < 1) del(src) //Never should happen + if(amount < 1) + qdel(src) //Never should happen var/list/recipes_list = recipes if(href_list["sublist"]) var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])] recipes_list = srl.recipes + var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])] var/multiplier = text2num(href_list["multiplier"]) - if(!multiplier) multiplier = 1 - if(src.amount < R.req_amount*multiplier) - if(R.req_amount*multiplier>1) - to_chat(usr, "\red You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!") + if(!multiplier) + multiplier = 1 + + if(amount < R.req_amount * multiplier) + if(R.req_amount * multiplier>1) + to_chat(usr, "You haven't got enough [src] to build \the [R.req_amount * multiplier] [R.title]\s!") else - to_chat(usr, "\red You haven't got enough [src] to build \the [R.title]!") - return + to_chat(usr, "You haven't got enough [src] to build \the [R.title]!") + return 0 + if(R.one_per_turf && (locate(R.result_type) in usr.loc)) - to_chat(usr, "\red There is another [R.title] here!") - return + to_chat(usr, "There is another [R.title] here!") + return 0 + if(R.on_floor && !istype(usr.loc, /turf/simulated)) - to_chat(usr, "\red \The [R.title] must be constructed on the floor!") - return + to_chat(usr, "\The [R.title] must be constructed on the floor!") + return 0 + if(R.time) - to_chat(usr, "\blue Building [R.title] ...") + to_chat(usr, "Building [R.title] ...") if(!do_after(usr, R.time, target = usr)) - return - if(src.amount < R.req_amount*multiplier) + return 0 + + if(amount < R.req_amount * multiplier) return - var/atom/O = new R.result_type( usr.loc ) + + var/atom/O = new R.result_type(usr.loc) O.dir = usr.dir - if(R.max_res_amount>1) + if(R.max_res_amount > 1) var/obj/item/stack/new_item = O - new_item.amount = R.res_amount*multiplier + new_item.amount = R.res_amount * multiplier //new_item.add_to_stacks(usr) - src.amount-=R.req_amount*multiplier - if(src.amount < 1) // Just in case a stack's amount ends up fractional somehow + + R.post_build(src, O) + + amount -= R.req_amount * multiplier + if(amount < 1) // Just in case a stack's amount ends up fractional somehow var/oldsrc = src src = null //dont kill proc after del() usr.unEquip(oldsrc, 1) - del(oldsrc) // Not qdel, because qdel'd stacks act strange for cyborgs - if(istype(O,/obj/item)) + qdel(oldsrc) + if(istype(O, /obj/item)) usr.put_in_hands(O) + O.add_fingerprint(usr) //BubbleWrap - so newly formed boxes are empty - if( istype(O, /obj/item/weapon/storage) ) + if(istype(O, /obj/item/weapon/storage)) for(var/obj/item/I in O) - del(I) + qdel(I) //BubbleWrap END - if(src && usr.machine==src) //do not reopen closed window - spawn( 0 ) - src.interact(usr) + + if(src && usr.machine == src) //do not reopen closed window + spawn(0) + interact(usr) return - return /obj/item/stack/proc/use(var/used) if(amount < used) @@ -169,19 +185,19 @@ if(usr) usr.unEquip(src, 1) spawn() - del(src) // Not qdel, because qdel'd stacks act strange for cyborgs + qdel(src) update_icon() return 1 -/obj/item/stack/proc/add_to_stacks(mob/usr as mob) +/obj/item/stack/proc/add_to_stacks(mob/usr) var/obj/item/stack/oldsrc = src src = null for(var/obj/item/stack/item in usr.loc) - if(item==oldsrc) + if(item == oldsrc) continue if(!istype(item, oldsrc.type)) continue - if(item.amount>=item.max_amount) + if(item.amount >= item.max_amount) continue oldsrc.attackby(item, usr) to_chat(usr, "You add new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s.") @@ -204,7 +220,7 @@ use(amt) return F -/obj/item/stack/attack_hand(mob/user as mob) +/obj/item/stack/attack_hand(mob/user) if(user.get_inactive_hand() == src) var/obj/item/stack/F = split(user, 1) user.put_in_hands(F) @@ -214,14 +230,15 @@ else ..() -/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob, params) +/obj/item/stack/attackby(obj/item/W, mob/user, params) ..() - if(istype(W, src.type)) + if(istype(W, type)) var/obj/item/stack/S = W if(S.amount >= max_amount) return 1 - var/to_transfer as num - if(user.get_inactive_hand()==src) + + var/to_transfer + if(user.get_inactive_hand() == src) var/desired = input("How much would you like to transfer from this stack?", "How much?", 1) as null|num if(!desired) return @@ -229,52 +246,22 @@ to_transfer = max(1,min(desired,S.max_amount-S.amount,src.amount)) else to_transfer = min(src.amount, S.max_amount-S.amount) - S.amount+=to_transfer - if(S && usr.machine==S) - spawn(0) S.interact(usr) - src.use(to_transfer) - if(src && usr.machine==src) - spawn(0) src.interact(usr) + + S.amount += to_transfer + if(S && usr.machine == S) + spawn(0) + S.interact(usr) + use(to_transfer) + if(src && usr.machine == src) + spawn(0) + interact(usr) S.update_icon() - else return ..() + else + return ..() -/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj) - src.blood_DNA = from.blood_DNA - src.fingerprints = from.fingerprints - src.fingerprintshidden = from.fingerprintshidden - src.fingerprintslast = from.fingerprintslast - //TODO bloody overlay - -/* - * Recipe datum - */ -/datum/stack_recipe - var/title = "ERROR" - var/result_type - var/req_amount = 1 - var/res_amount = 1 - var/max_res_amount = 1 - var/time = 0 - var/one_per_turf = 0 - var/on_floor = 0 - New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0) - src.title = title - src.result_type = result_type - src.req_amount = req_amount - src.res_amount = res_amount - src.max_res_amount = max_res_amount - src.time = time - src.one_per_turf = one_per_turf - src.on_floor = on_floor - -/* - * Recipe list datum - */ -/datum/stack_recipe_list - var/title = "ERROR" - var/list/recipes = null - var/req_amount = 1 - New(title, recipes, req_amount = 1) - src.title = title - src.recipes = recipes - src.req_amount = req_amount +/obj/item/stack/proc/copy_evidences(obj/item/stack/from) + blood_DNA = from.blood_DNA + fingerprints = from.fingerprints + fingerprintshidden = from.fingerprintshidden + fingerprintslast = from.fingerprintslast + //TODO bloody overlay \ No newline at end of file diff --git a/code/game/objects/items/stacks/stack_recipe.dm b/code/game/objects/items/stacks/stack_recipe.dm new file mode 100644 index 00000000000..4fe283c6db6 --- /dev/null +++ b/code/game/objects/items/stacks/stack_recipe.dm @@ -0,0 +1,55 @@ + +/* + * Recipe datum + */ +/datum/stack_recipe + var/title = "ERROR" + var/result_type + var/req_amount = 1 + var/res_amount = 1 + var/max_res_amount = 1 + var/time = 0 + var/one_per_turf = 0 + var/on_floor = 0 + +/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0) + src.title = title + src.result_type = result_type + src.req_amount = req_amount + src.res_amount = res_amount + src.max_res_amount = max_res_amount + src.time = time + src.one_per_turf = one_per_turf + src.on_floor = on_floor + +/datum/stack_recipe/proc/post_build(var/obj/item/stack/S, var/obj/result) + return + +/* Special Recipes */ + +/datum/stack_recipe/cable_restraints +/datum/stack_recipe/cable_restraints/post_build(var/obj/item/stack/S, var/obj/result) + if(istype(result, /obj/item/weapon/restraints/handcuffs/cable)) + result.color = S.color + ..() + +/datum/stack_recipe/rods +/datum/stack_recipe/rods/post_build(var/obj/item/stack/S, var/obj/result) + if(istype(result, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = result + R.update_icon() + ..() + +/* + * Recipe list datum + */ +/datum/stack_recipe_list + var/title = "ERROR" + var/list/recipes = null + var/req_amount = 1 + +/datum/stack_recipe_list/New(title, recipes, req_amount = 1) + src.title = title + src.recipes = recipes + src.req_amount = req_amount + diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index d7fcf1bcb53..bfbd0a4ccb6 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -37,6 +37,7 @@ icon_state = "tile_grass" origin_tech = "biotech=1" turf_type = /turf/simulated/floor/grass + burn_state = FLAMMABLE /* * Wood @@ -48,6 +49,7 @@ desc = "an easy to fit wood floor tile" icon_state = "tile-wood" turf_type = /turf/simulated/floor/wood + burn_state = FLAMMABLE /* * Carpets @@ -58,6 +60,7 @@ desc = "A piece of carpet. It is the same size as a floor tile" icon_state = "tile-carpet" turf_type = /turf/simulated/floor/carpet + burn_state = FLAMMABLE /* * Plasteel @@ -100,6 +103,7 @@ desc = "A piece of carpet with a convincing star pattern." icon_state = "tile_space" turf_type = /turf/simulated/floor/fakespace + burn_state = FLAMMABLE /obj/item/stack/tile/fakespace/loaded amount = 30 diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index ec524314b71..7e38c7a6e4e 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -257,31 +257,31 @@ icon = 'icons/obj/toy.dmi' icon_state = "snappop" w_class = 1 + var/ash_type = /obj/effect/decal/cleanable/ash -/obj/item/toy/snappop/throw_impact(atom/hit_atom) - ..() - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, src) +/obj/item/toy/snappop/proc/pop_burst(var/n=3, var/c=1) + var/datum/effect/system/spark_spread/s = new() + s.set_up(n, c, src) s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - visible_message("The [src.name] explodes!","You hear a snap!") + new ash_type(loc) + visible_message("[src] explodes!", + "You hear a snap!") playsound(src, 'sound/effects/snap.ogg', 50, 1) qdel(src) +/obj/item/toy/snappop/fire_act() + pop_burst() + +/obj/item/toy/snappop/throw_impact(atom/hit_atom) + ..() + pop_burst() + /obj/item/toy/snappop/Crossed(H as mob|obj) - if((ishuman(H))) //i guess carp and shit shouldn't set them off + if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off var/mob/living/carbon/M = H - if(M.m_intent == "run") - to_chat(M, "You step on the snap pop!") - - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(2, 0, src) - s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - visible_message("The [name] explodes!","You hear a snap!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) - + if(issilicon(H) || M.m_intent == "run") + to_chat(M, "You step on the snap pop!") + pop_burst(2, 0) /* @@ -394,6 +394,8 @@ obj/item/toy/cards + burn_state = FLAMMABLE + burntime = 5 var/parentdeck = null var/deckstyle = "nanotrasen" var/card_hitsound = null @@ -749,6 +751,7 @@ obj/item/toy/cards/deck/syndicate card_throw_speed = 3 card_throw_range = 20 card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut") + burn_state = FIRE_PROOF /* || Custom card decks || @@ -884,6 +887,7 @@ obj/item/toy/cards/deck/syndicate/black icon_state = "carpplushie" attack_verb = list("bitten", "eaten", "fin slapped") var/bitesound = 'sound/weapons/bite.ogg' + burn_state = FLAMMABLE // Attack mob /obj/item/toy/carpplushie/attack(mob/M as mob, mob/user as mob) @@ -946,6 +950,7 @@ obj/item/toy/cards/deck/syndicate/black icon = 'icons/obj/toy.dmi' var/poof_sound = 'sound/weapons/thudswoosh.ogg' attack_verb = list("poofed", "bopped", "whapped","cuddled","fluffed") + burn_state = FLAMMABLE /obj/item/toy/plushie/attack(mob/M as mob, mob/user as mob) playsound(loc, poof_sound, 20, 1) // Play the whoosh sound in local area @@ -1071,6 +1076,7 @@ obj/item/toy/cards/deck/syndicate/black item_state = "arm_blade" attack_verb = list("pricked", "absorbed", "gored") w_class = 2 + burn_state = FLAMMABLE /* * Toy/fake flash diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 928eba59a6a..dc538674993 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -6,6 +6,7 @@ icon = 'icons/obj/trash.dmi' w_class = 1 desc = "This is rubbish." + burn_state = FLAMMABLE /obj/item/trash/raisins name = "4no raisins" @@ -42,6 +43,7 @@ /obj/item/trash/plate name = "Plate" icon_state = "plate" + burn_state = FIRE_PROOF /obj/item/trash/snack_bowl name = "Snack bowl" @@ -58,6 +60,7 @@ /obj/item/trash/tray name = "Tray" icon_state = "tray" + burn_state = FIRE_PROOF /obj/item/trash/candle name = "candle" @@ -73,6 +76,7 @@ icon_state = "cola" var/is_glass = 0 var/is_plastic = 0 + burn_state = FIRE_PROOF /obj/item/trash/gum name = "chewed gum" diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 44ef04ab401..a0dcdaec042 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -91,13 +91,13 @@ RCD data["max_matter"] = max_matter data["one_access"] = one_access data["locked"] = locked - + if(menu == 2) var/list/door_types_list = list() for(var/type in allowed_door_types) door_types_list[++door_types_list.len] = list("name" = allowed_door_types[type], "type" = type) data["allowed_door_types"] = door_types_list - + data["door_accesses"] = door_accesses_list ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -110,14 +110,14 @@ RCD /obj/item/weapon/rcd/Topic(href, href_list, nowindow, state) if(..()) return 1 - + if(prob(20)) spark_system.start() - + if(href_list["mode"]) mode = text2num(href_list["mode"]) . = 1 - + if(href_list["door_type"]) var/new_door_type = text2path(href_list["door_type"]) if(!(new_door_type in allowed_door_types)) @@ -125,11 +125,11 @@ RCD return door_type = new_door_type . = 1 - + if(href_list["menu"]) menu = text2num(href_list["menu"]) . = 1 - + if(href_list["login"]) if(istype(usr,/mob/living/silicon)) locked = 0 @@ -142,15 +142,15 @@ RCD if(istype(ID) && ID && check_access(ID)) locked = 0 . = 1 - + if(href_list["logout"]) locked = 1 . = 1 - + if(href_list["toggle_one_access"] && !locked) one_access = !one_access . = 1 - + if(href_list["toggle_access"] && !locked) var/href_access = text2num(href_list["toggle_access"]) if(href_access in door_accesses) @@ -251,10 +251,10 @@ RCD qdel(A) return 1 return 0 - + if(istype(A, /obj/structure/window)) // You mean the grille of course, do you? A = locate(/obj/structure/grille) in A.loc - + if(istype(A, /obj/structure/grille)) if(!checkResource(2, user)) return 0 @@ -326,7 +326,7 @@ RCD else to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") return 0 - + nanomanager.update_uis(src) /obj/item/weapon/rcd/proc/useResource(var/amount, var/mob/user) @@ -354,6 +354,18 @@ RCD desc = "A device used to rapidly build and deconstruct walls and floors." canRwall = 1 + +/obj/item/weapon/rcd/proc/detonate_pulse() + audible_message("[src] begins to vibrate and \ + buzz loudly!","[src] begins \ + vibrating violently!") + // 5 seconds to get rid of it + addtimer(src, "detonate_pulse_explode", 50) + +/obj/item/weapon/rcd/proc/detonate_pulse_explode() + explosion(src, 0, 0, 3, 1, flame_range = 1) + qdel(src) + /obj/item/weapon/rcd/combat name = "combat RCD" max_matter = 500 diff --git a/code/game/objects/items/weapons/bee_briefcase.dm b/code/game/objects/items/weapons/bee_briefcase.dm index 665ad549bd2..98f3fc1709b 100644 --- a/code/game/objects/items/weapons/bee_briefcase.dm +++ b/code/game/objects/items/weapons/bee_briefcase.dm @@ -64,6 +64,7 @@ //Play sound through the station intercomms, so everyone knows the doom you have wrought. for(var/O in global_intercoms) var/obj/item/device/radio/intercom/I = O + // TODO: Tie into space manager if(I.z != ZLEVEL_STATION) //Only broadcast to the station intercoms continue if(!I.on) //Only broadcast to active intercoms (powered, switched on) @@ -75,4 +76,4 @@ var/mob/living/simple_animal/hostile/poison/bees/syndi/B = new /mob/living/simple_animal/hostile/poison/bees/syndi(null) B.master_and_friends = blood_list //Doesn't automatically add the person who opens the case, so the bees will attack the user unless they gave their blood B.forceMove(get_turf(user)) //RELEASE THE BEES! - bees_left -= 5 \ No newline at end of file + bees_left -= 5 diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 0ee843fe85c..d1721c5c247 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -105,13 +105,13 @@ var/photo var/dat var/stamped = 0 - + var/obj/item/weapon/card/id/guest/guest_pass = null // Guest pass attached to the ID /obj/item/weapon/card/id/New() ..() spawn(30) - if(ishuman(loc)) + if(ishuman(loc) && blood_type == "\[UNSET\]") var/mob/living/carbon/human/H = loc SetOwnerInfo(H) @@ -242,10 +242,10 @@ set name = "Remove Guest Pass" set category = "Object" set src in range(0) - + if(usr.stat || !usr.canmove || usr.restrained()) return - + if(guest_pass) to_chat(usr, "You remove the guest pass from this ID.") guest_pass.forceMove(get_turf(src)) @@ -253,6 +253,37 @@ else to_chat(usr, "There is no guest pass attached to this ID") +/obj/item/weapon/card/id/serialize() + var/list/data = ..() + + data["sex"] = sex + data["age"] = age + data["btype"] = blood_type + data["dna_hash"] = dna_hash + data["fprint_hash"] = fingerprint_hash + data["access"] = access + data["job"] = assignment + data["account"] = associated_account_number + data["owner"] = registered_name + data["mining"] = mining_points + return data + +/obj/item/weapon/card/id/deserialize(list/data) + sex = data["sex"] + age = data["age"] + blood_type = data["btype"] + dna_hash = data["dna_hash"] + fingerprint_hash = data["fprint_hash"] + access = data["access"] // No need for a copy, the list isn't getting touched + assignment = data["job"] + associated_account_number = data["account"] + registered_name = data["owner"] + mining_points = data["mining"] + // We'd need to use icon serialization(b64) to save the photo, and I don't feel like i + UpdateName() + RebuildHTML() + ..() + /obj/item/weapon/card/id/silver name = "identification card" desc = "A silver card which shows honour and dedication." @@ -767,4 +798,4 @@ if("TDgreen") return "Thunderdome Green" else - return capitalize(skin) \ No newline at end of file + return capitalize(skin) diff --git a/code/game/objects/items/weapons/cash.dm b/code/game/objects/items/weapons/cash.dm index 7c1432bb772..3608d7861f3 100644 --- a/code/game/objects/items/weapons/cash.dm +++ b/code/game/objects/items/weapons/cash.dm @@ -23,6 +23,7 @@ var/global/list/moneytypes=list( throw_speed = 1 throw_range = 2 w_class = 1 + burn_state = FLAMMABLE var/access = list() access = access_crate_cash var/worth = 1 // Per chip diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm index a06619fcca4..8449e17a9db 100644 --- a/code/game/objects/items/weapons/cigs.dm +++ b/code/game/objects/items/weapons/cigs.dm @@ -59,6 +59,9 @@ LIGHTERS ARE IN LIGHTERS.DM return ..() +/obj/item/clothing/mask/cigarette/fire_act() + light() + /obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W as obj, mob/user as mob, params) ..() if(istype(W, /obj/item/weapon/weldingtool)) @@ -110,7 +113,7 @@ LIGHTERS ARE IN LIGHTERS.DM to_chat(user, "[src] is full.") -/obj/item/clothing/mask/cigarette/proc/light(var/flavor_text = "[usr] lights the [name].") +/obj/item/clothing/mask/cigarette/proc/light(flavor_text = null) if(!src.lit) src.lit = 1 damtype = "fire" @@ -136,8 +139,9 @@ LIGHTERS ARE IN LIGHTERS.DM reagents.handle_reactions() icon_state = icon_on item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) + if(flavor_text) + var/turf/T = get_turf(src) + T.visible_message(flavor_text) set_light(2, 0.25, "#E38F46") processing_objects.Add(src) @@ -321,14 +325,15 @@ LIGHTERS ARE IN LIGHTERS.DM ..() reagents.add_reagent("nicotine", chem_volume) -/obj/item/clothing/mask/cigarette/pipe/light(var/flavor_text = "[usr] lights the [name].") +/obj/item/clothing/mask/cigarette/pipe/light(flavor_text = null) if(!src.lit) src.lit = 1 damtype = "fire" icon_state = icon_on item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) + if(flavor_text) + var/turf/T = get_turf(src) + T.visible_message(flavor_text) processing_objects.Add(src) /obj/item/clothing/mask/cigarette/pipe/process() diff --git a/code/game/objects/items/weapons/courtroom.dm b/code/game/objects/items/weapons/courtroom.dm index f070a1fe4ad..055faa03a8c 100644 --- a/code/game/objects/items/weapons/courtroom.dm +++ b/code/game/objects/items/weapons/courtroom.dm @@ -11,6 +11,7 @@ throwforce = 6.0 w_class = 2 attack_verb = list("bashed", "battered", "judged", "whacked") + burn_state = FLAMMABLE /obj/item/weapon/gavelhammer/suicide_act(mob/user) user.visible_message("[user] has sentenced \himself to death with the [src.name]! It looks like \he's trying to commit suicide.") @@ -25,6 +26,7 @@ force = 2.0 throwforce = 2.0 w_class = 1 + burn_state = FLAMMABLE /obj/item/weapon/gavelblock/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/gavelhammer)) diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 0ec893b53a6..6dcbef385b0 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -13,6 +13,7 @@ icon = 'icons/obj/items.dmi' icon_state = "gift1" item_state = "gift1" + burn_state = FLAMMABLE /obj/item/weapon/a_gift/New() ..() @@ -139,6 +140,7 @@ flags = NOBLUDGEON amount = 25 max_amount = 25 + burn_state = FLAMMABLE /obj/item/stack/wrapping_paper/attack_self(mob/user) to_chat(user, "You need to use it on a package that has already been wrapped!") diff --git a/code/game/objects/items/weapons/grenades/atmosgrenade.dm b/code/game/objects/items/weapons/grenades/atmosgrenade.dm new file mode 100644 index 00000000000..4bfda1ab659 --- /dev/null +++ b/code/game/objects/items/weapons/grenades/atmosgrenade.dm @@ -0,0 +1,24 @@ + + + +/obj/item/weapon/grenade/gas + name = "Plasma Fire Grenade" + desc = "A compressed plasma grenade, used to start horrific plasma fires." + origin_tech = "materials=3;magnets=4;syndicate=4" + icon = 'icons/obj/grenade.dmi' + icon_state = "syndicate" + item_state = "flashbang" + var/spawn_contents = SPAWN_HEAT | SPAWN_TOXINS + var/spawn_amount = 100 + +/obj/item/weapon/grenade/gas/prime() + var/turf/simulated/target_turf = get_turf(src) + if(istype(target_turf)) + target_turf.atmos_spawn_air(spawn_contents, spawn_amount) + target_turf.air_update_turf() + qdel(src) + +/obj/item/weapon/grenade/gas/knockout + name = "Knockout Grenade" + desc = "A grenade that completely removes all air and heat from its detonation area." + spawn_contents = SPAWN_20C | SPAWN_N2O \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/clusterbuster.dm b/code/game/objects/items/weapons/grenades/clusterbuster.dm index 8ba1782cf18..851c625b765 100644 --- a/code/game/objects/items/weapons/grenades/clusterbuster.dm +++ b/code/game/objects/items/weapons/grenades/clusterbuster.dm @@ -242,6 +242,16 @@ desc = "Reserved for those pesky request." payload = /mob/living/simple_animal/crab +/obj/item/weapon/grenade/clusterbuster/plasma + name = "Plasma Cluster Grenade" + desc = "For when everything needs to die in a fire." + payload = /obj/item/weapon/grenade/gas + +/obj/item/weapon/grenade/clusterbuster/n2o + name = "N2O Cluster Grenade" + desc = "For when you need to knock out EVERYONE." + payload = /obj/item/weapon/grenade/gas/knockout + ////////////Clusterbuster of Clusterbusters//////////// /obj/item/weapon/grenade/clusterbuster/mega_fox diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 8cbd76041bd..af855e63016 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -9,6 +9,8 @@ throw_range = 20 flags = CONDUCT slot_flags = SLOT_BELT + burn_state = FLAMMABLE + burntime = 5 var/active = 0 var/det_time = 50 var/display_timer = 1 diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 2fb7b0de0b8..4e63ee67497 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -65,7 +65,7 @@ /obj/item/weapon/restraints/handcuffs/cable name = "cable restraints" desc = "Looks like some cables tied together. Could be used to tie something up." - icon_state = "cuff_red" + icon_state = "cuff_white" materials = list(MAT_METAL=150, MAT_GLASS=75) breakouttime = 300 //Deciseconds = 30s cuffsound = 'sound/weapons/cablecuff.ogg' diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 8b5baf79a35..12219eadd0b 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -11,6 +11,7 @@ throw_range = 7 w_class = 3 attack_verb = list("mopped", "bashed", "bludgeoned", "whacked") + burn_state = FLAMMABLE var/mopping = 0 var/mopcount = 0 var/mopcap = 5 diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm index a7741267d09..67d4f078264 100644 --- a/code/game/objects/items/weapons/paint.dm +++ b/code/game/objects/items/weapons/paint.dm @@ -8,6 +8,8 @@ item_state = "paintcan" materials = list(MAT_METAL=200) w_class = 3 + burn_state = FLAMMABLE + burntime = 5 amount_per_transfer_from_this = 5 possible_transfer_amounts = list(5,10,20,30,50,70) volume = 70 diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index d7c33164543..3e8dbb6239d 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -16,6 +16,14 @@ var/list/loadedItems = list() //The items loaded into the cannon that will be fired out var/pressureSetting = 1 //How powerful the cannon is - higher pressure = more gas but more powerful throws +/obj/item/weapon/pneumatic_cannon/Destroy() + if(tank) + qdel(tank) + tank = null + for(var/obj/item/I in loadedItems) + qdel(I) + loadedItems.Cut() + return ..() /obj/item/weapon/pneumatic_cannon/examine(mob/user) ..() diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm index 90c98c6fdac..de419dc1b7d 100644 --- a/code/game/objects/items/weapons/scrolls.dm +++ b/code/game/objects/items/weapons/scrolls.dm @@ -9,6 +9,7 @@ throw_speed = 4 throw_range = 20 origin_tech = "bluespace=4" + burn_state = FLAMMABLE /obj/item/weapon/teleportation_scroll/apprentice name = "lesser scroll of teleportation" diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 809bf0d298d..be831bbe0d1 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -44,6 +44,7 @@ icon_state = "buckler" item_state = "buckler" materials = list() + burn_state = FLAMMABLE block_chance = 30 /obj/item/weapon/shield/energy diff --git a/code/game/objects/items/weapons/signs.dm b/code/game/objects/items/weapons/signs.dm index 00ac859528d..fa68b09135e 100644 --- a/code/game/objects/items/weapons/signs.dm +++ b/code/game/objects/items/weapons/signs.dm @@ -6,6 +6,7 @@ force = 5 w_class = 4 attack_verb = list("bashed","smacked") + burn_state = FLAMMABLE var/delayed = 0 //used to do delays diff --git a/code/game/objects/items/weapons/staff.dm b/code/game/objects/items/weapons/staff.dm index ffaadb59d59..19c771873ce 100644 --- a/code/game/objects/items/weapons/staff.dm +++ b/code/game/objects/items/weapons/staff.dm @@ -10,6 +10,7 @@ w_class = 2 armour_penetration = 100 attack_verb = list("bludgeoned", "whacked", "disciplined") + burn_state = FLAMMABLE /obj/item/weapon/twohanded/staff/broom name = "broom" diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index fa8de4f51bf..c664ca9fff9 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -15,6 +15,8 @@ max_w_class = 3 max_combined_w_class = 21 storage_slots = 21 + burn_state = FLAMMABLE + burntime = 20 species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/back.dmi' @@ -22,7 +24,7 @@ /obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob, params) playsound(src.loc, "rustle", 50, 1, -5) - ..() + return ..() /* * Backpack Types @@ -35,6 +37,7 @@ icon_state = "holdingpack" max_w_class = 5 max_combined_w_class = 35 + burn_state = FIRE_PROOF New() ..() @@ -123,12 +126,14 @@ desc = "It's a special backpack made exclusively for Nanotrasen officers." icon_state = "captainpack" item_state = "captainpack" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/industrial name = "industrial backpack" desc = "It's a tough backpack for the daily grind of station life." icon_state = "engiepack" item_state = "engiepack" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/botany name = "botany backpack" @@ -153,6 +158,7 @@ desc = "A specially designed backpack. It's fire resistant and smells vaguely of plasma." icon_state = "toxpack" item_state = "toxpack" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/virology name = "virology backpack" @@ -168,6 +174,7 @@ name = "leather satchel" desc = "It's a very fancy satchel made with fine leather." icon_state = "satchel" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/satcheldeluxe name = "leather satchel" @@ -188,6 +195,7 @@ name = "industrial satchel" desc = "A tough satchel with extra pockets." icon_state = "satchel-eng" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/satchel_med name = "medical satchel" @@ -213,6 +221,7 @@ name = "scientist satchel" desc = "Useful for holding research materials." icon_state = "satchel-tox" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/satchel_sec name = "security satchel" @@ -228,6 +237,7 @@ name = "captain's satchel" desc = "An exclusive satchel for Nanotrasen officers." icon_state = "satchel-cap" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/satchel_flat name = "smuggler's satchel" @@ -266,8 +276,8 @@ slowdown = 1 /obj/item/weapon/storage/backpack/duffel/syndie - name = "suspicious looking dufflebag" - desc = "A large dufflebag for holding extra tactical supplies." + name = "suspicious looking duffelbag" + desc = "A large duffelbag for holding extra tactical supplies." icon_state = "duffel-syndi" item_state = "duffel-syndimed" origin_tech = "syndicate=1" @@ -287,7 +297,7 @@ item_state = "duffel-syndiammo" /obj/item/weapon/storage/backpack/duffel/syndie/ammo/loaded - desc = "A large dufflebag, packed to the brim with Bulldog shotgun ammo." + desc = "A large duffelbag, packed to the brim with Bulldog shotgun ammo." /obj/item/weapon/storage/backpack/duffel/syndie/ammo/loaded/New() ..() @@ -302,10 +312,10 @@ new /obj/item/ammo_box/magazine/m12g/dragon(src) /obj/item/weapon/storage/backpack/duffel/syndie/surgery - name = "surgery dufflebag" - desc = "A suspicious looking dufflebag for holding surgery tools." + name = "surgery duffelbag" + desc = "A suspicious looking duffelbag for holding surgery tools." icon_state = "duffel-syndimed" - item_state = "duffle-syndimed" + item_state = "duffel-syndimed" /obj/item/weapon/storage/backpack/duffel/syndie/surgery/New() ..() @@ -323,10 +333,10 @@ new /obj/item/device/mmi/syndie(src) /obj/item/weapon/storage/backpack/duffel/syndie/surgery_fake //for maint spawns - name = "surgery dufflebag" - desc = "A suspicious looking dufflebag for holding surgery tools." + name = "surgery duffelbag" + desc = "A suspicious looking duffelbag for holding surgery tools." icon_state = "duffel-syndimed" - item_state = "duffle-syndimed" + item_state = "duffel-syndimed" /obj/item/weapon/storage/backpack/duffel/syndie/surgery_fake/New() ..() @@ -346,6 +356,7 @@ desc = "A duffelbag designed to hold large quantities of condoms." icon_state = "duffel-captain" item_state = "duffel-captain" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/duffel/security name = "security duffelbag" @@ -388,6 +399,7 @@ desc = "A duffelbag designed to hold tools." icon_state = "duffel-eng" item_state = "duffel-eng" + burn_state = FIRE_PROOF /obj/item/weapon/storage/backpack/duffel/hydro name = "hydroponics duffelbag" diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 66cb11a9dd6..395d27d0300 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -162,7 +162,7 @@ max_w_class = 3 w_class = 1 can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown", "/obj/item/stack/tile/grass","/obj/item/stack/medical/ointment/aloe","/obj/item/stack/medical/bruise_pack/comfrey", "/obj/item/weapon/reagent_containers/honeycomb") - + burn_state = FLAMMABLE /obj/item/weapon/storage/bag/plants/portaseeder name = "portable seed extractor" @@ -375,7 +375,8 @@ max_combined_w_class = 21 max_w_class = 3 w_class = 4 //Bigger than a book because physics - can_hold = list("/obj/item/weapon/book", "/obj/item/weapon/spellbook") //No bibles, consistent with bookcase + can_hold = list("/obj/item/weapon/book", "/obj/item/weapon/storage/bible", "/obj/item/weapon/tome", "/obj/item/weapon/spellbook") + burn_state = FLAMMABLE /* * Trays - Agouri @@ -484,7 +485,7 @@ max_combined_w_class = 200 w_class = 1 can_hold = list("/obj/item/weapon/reagent_containers/food/pill","/obj/item/weapon/reagent_containers/glass/beaker","/obj/item/weapon/reagent_containers/glass/bottle") - + burn_state = FLAMMABLE /* * Biowaste bag (mostly for xenobiologists) */ @@ -497,4 +498,5 @@ storage_slots = 25 max_combined_w_class = 200 w_class = 1 - can_hold = list("/obj/item/slime_extract","/obj/item/weapon/reagent_containers/food/snacks/monkeycube","/obj/item/weapon/reagent_containers/syringe","/obj/item/weapon/reagent_containers/glass/beaker","/obj/item/weapon/reagent_containers/glass/bottle","/obj/item/weapon/reagent_containers/blood","/obj/item/weapon/reagent_containers/hypospray/autoinjector") \ No newline at end of file + can_hold = list("/obj/item/slime_extract","/obj/item/weapon/reagent_containers/food/snacks/monkeycube","/obj/item/weapon/reagent_containers/syringe","/obj/item/weapon/reagent_containers/glass/beaker","/obj/item/weapon/reagent_containers/glass/bottle","/obj/item/weapon/reagent_containers/blood","/obj/item/weapon/reagent_containers/hypospray/autoinjector") + burn_state = FLAMMABLE \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index a0e3d4dd69e..23f8f9ea685 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -37,7 +37,9 @@ src.add_fingerprint(usr) return - +/obj/item/weapon/storage/belt/deserialize(list/data) + ..() + update_icon() /obj/item/weapon/storage/belt/utility name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing. diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 57332ae24d6..b98805e3275 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -5,6 +5,7 @@ throw_speed = 1 throw_range = 5 w_class = 3 + burn_state = FLAMMABLE var/mob/affecting = null var/deity_name = "Christ" diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 76cbc9ab102..bfdc3a80727 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -24,6 +24,7 @@ desc = "It's just an ordinary box." icon_state = "box" item_state = "syringe_kit" + burn_state = FLAMMABLE foldable = /obj/item/stack/sheet/cardboard //BubbleWrap /obj/item/weapon/storage/box/large diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 543865aa592..7f2a91054c1 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -12,6 +12,8 @@ max_w_class = 3 max_combined_w_class = 21 attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") + burn_state = FLAMMABLE + burntime = 20 /obj/item/weapon/storage/briefcase/New() ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 367874b0d7d..c4488216b12 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -17,6 +17,7 @@ icon = 'icons/obj/food/food.dmi' icon_state = "donutbox6" name = "donut box" + burn_state = FLAMMABLE var/icon_type = "donut" /obj/item/weapon/storage/fancy/update_icon(var/itemremoved = 0) diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 0c03e65beab..03ba6bed54b 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -138,15 +138,15 @@ /obj/item/weapon/storage/firstaid/adv/New() ..() - if(empty) return - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - new /obj/item/stack/medical/bruise_pack/advanced(src) + if(empty) + return + new /obj/item/stack/medical/bruise_pack(src) new /obj/item/stack/medical/bruise_pack/advanced(src) new /obj/item/stack/medical/bruise_pack/advanced(src) new /obj/item/stack/medical/ointment/advanced(src) new /obj/item/stack/medical/ointment/advanced(src) - new /obj/item/stack/medical/splint(src) - return + new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) + new /obj/item/device/healthanalyzer(src) /obj/item/weapon/storage/firstaid/adv/empty empty = 1 diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index e2324fcb434..c34b392430e 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -323,7 +323,7 @@ return 1 //Call this proc to handle the removal of an item from the storage item. The item will be moved to the atom sent as new_target -/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location) +/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location, burn = 0) if(!istype(W)) return 0 if(istype(src, /obj/item/weapon/storage/fancy)) @@ -357,8 +357,14 @@ W.on_exit_storage(src) update_icon() W.mouse_opacity = initial(W.mouse_opacity) + if(burn) + W.fire_act() return 1 +/obj/item/weapon/storage/empty_object_contents(burn, loc) + for(var/obj/item/Item in contents) + remove_from_storage(Item, loc, burn) + //This proc is called when you want to place an item into the storage item. /obj/item/weapon/storage/attackby(obj/item/W as obj, mob/user as mob, params) ..() @@ -541,3 +547,34 @@ return depth +/obj/item/weapon/storage/serialize() + var data = ..() + var/list/content_list = list() + data["content"] = content_list + data["slots"] = storage_slots + data["max_w_class"] = max_w_class + data["max_c_w_class"] = max_combined_w_class + for(var/thing in contents) + var/atom/movable/AM = thing + // This code does not watch out for infinite loops + // But then again a tesseract would destroy the server anyways + // Also I wish I could just insert a list instead of it reading it the wrong way + content_list.len++ + content_list[content_list.len] = AM.serialize() + return data + +/obj/item/weapon/storage/deserialize(list/data) + if(isnum(data["slots"])) + storage_slots = data["slots"] + if(isnum(data["max_w_class"])) + max_w_class = data["max_w_class"] + if(isnum(data["max_c_w_class"])) + max_combined_w_class = data["max_c_w_class"] + for(var/thing in contents) + qdel(thing) // out with the old + for(var/thing in data["content"]) + if(islist(thing)) + list_to_object(thing, src) + else + log_debug("Non-list thing: [thing]. We are a [name]") + ..() diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 71d488672aa..ac994fe4b77 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -195,4 +195,13 @@ new /obj/item/ammo_casing/shotgun/dart/assassination(src) new /obj/item/ammo_casing/shotgun/dart/assassination(src) new /obj/item/ammo_casing/shotgun/dart/assassination(src) - new /obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane(src) \ No newline at end of file + new /obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane(src) + + +/obj/item/weapon/storage/box/syndie_kit/atmosgasgrenades + name = "Atmos Grenades" + +/obj/item/weapon/storage/box/syndie_kit/atmosgasgrenades/New() + ..() + new /obj/item/weapon/grenade/clusterbuster/plasma(src) + new /obj/item/weapon/grenade/clusterbuster/n2o(src) diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index e34f9687d7e..5bc1ae65e84 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -5,6 +5,7 @@ icon = 'icons/obj/wallets.dmi' icon_state = "wallet" w_class = 2 + burn_state = FLAMMABLE can_hold = list( "/obj/item/weapon/spacecash", "/obj/item/weapon/card", diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index c0935f5d316..3e7b63857cb 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -23,6 +23,12 @@ update_icon() return +/obj/item/weapon/melee/baton/Destroy() + if(bcell) + qdel(bcell) + bcell = null + return ..() + /obj/item/weapon/melee/baton/CheckParts(list/parts_list) ..() bcell = locate(/obj/item/weapon/stock_parts/cell) in contents diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm index 62c2f7aabfd..3073125bae0 100644 --- a/code/game/objects/items/weapons/table_rack_parts.dm +++ b/code/game/objects/items/weapons/table_rack_parts.dm @@ -40,6 +40,7 @@ icon_state = "wood_tableparts" flags = null upgradable = 0 + burn_state = FLAMMABLE result = /obj/structure/table/woodentable parts = list( /obj/item/stack/sheet/wood, diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 9415e49d3cd..4ec1b1587c8 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -35,6 +35,7 @@ /obj/item/weapon/tank/Destroy() if(air_contents) qdel(air_contents) + air_contents = null processing_objects.Remove(src) diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index e6e88563d4b..9068460ae80 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -373,7 +373,8 @@ V.visible_message("[V] was frozen shut!") for(var/mob/living/L in T) L.ExtinguishMob() - return + for(var/obj/item/Item in T) + Item.extinguish() /datum/effect/system/freezing_smoke_spread diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 4728e8c730e..decfa424872 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -48,6 +48,7 @@ Frequency: return 1 var/turf/current_location = get_turf(usr)//What turf is the user on? + // TODO: Tie into space manager if(!current_location ||( current_location.z in config.admin_levels))//If turf was not found or they're on z level 2. to_chat(usr, "\The [src] is malfunctioning.") return 1 @@ -61,6 +62,7 @@ Frequency: for(var/obj/item/device/radio/beacon/W in beacons) if(W.frequency == frequency && !W.syndicate) + // TODO: Tie into space manager if(W && W.z == z) var/turf/TB = get_turf(W) temp += "[W.code]: [TB.x], [TB.y], [TB.z]
    " @@ -107,7 +109,8 @@ Frequency: /obj/item/weapon/hand_tele/attack_self(mob/user as mob) var/turf/current_location = get_turf(user)//What turf is the user on? - if(!current_location||(current_location.z in config.admin_levels)||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist. + // TODO: Tie into space manager + if(!current_location||(current_location.z in config.admin_levels)||current_location.z>=ZLEVEL_EMPTY)//If turf was not found or they're on z level 2 or >7 which does not currently exist. to_chat(user, "\The [src] is malfunctioning.") return var/list/L = list( ) diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 88138657270..da21397529d 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -140,7 +140,7 @@ if(get_dist(src,user) > 1) return 0 if(H != null) - user.visible_message("[src.name] is too cumbersome to carry in one hand!") + to_chat(user, "[src.name] is too cumbersome to carry in one hand!") return var/obj/item/weapon/twohanded/offhand/O = new(user) user.put_in_inactive_hand(O) @@ -365,6 +365,7 @@ if(!L.stat && prob(50)) var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) M.faction = user.faction.Copy() + M.attack_sound = hitsound M.Copy_Parent(user, 100, user.health/2.5, 12, 30) M.GiveTarget(L) @@ -693,3 +694,55 @@ Z.ex_act(2) charged = 3 playsound(user, 'sound/weapons/marauder.ogg', 50, 1) + +// Energized Fire axe +/obj/item/weapon/twohanded/energizedfireaxe + name = "energized fire axe" + desc = "Someone with a love for fire axes decided to turn one into a single-charge energy weapon. Seems excessive." + icon_state = "fireaxe0" + force = 5 + throwforce = 15 + sharp = 1 + edge = 1 + w_class = 5 + armour_penetration = 20 + slot_flags = SLOT_BACK + force_unwielded = 5 + force_wielded = 30 + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + var/charged = 1 + +/obj/item/weapon/twohanded/energizedfireaxe/update_icon() + if(wielded) + icon_state = "fireaxe2" + else + icon_state = "fireaxe0" + +/obj/item/weapon/twohanded/energizedfireaxe/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(wielded) + if(istype(A, /mob/living)) + var/mob/living/Z = A + if(charged) + charged-- + Z.take_organ_damage(0,30) + user.visible_message("[user] slams the charged axe into [Z.name] with all their might!") + playsound(loc, 'sound/magic/lightningbolt.ogg', 5, 1) + var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread + sparks.set_up(1, 1, src) + sparks.start() + + if(A && wielded && (istype(A, /obj/structure/window) || istype(A, /obj/structure/grille))) + if(istype(A, /obj/structure/window)) + var/obj/structure/window/W = A + W.destroy() + if(prob(4)) + charged++ + user.visible_message("The axe starts to emit an electric buzz!") + else + qdel(A) + if(prob(4)) + charged++ + user.visible_message("The axe starts to emit an electric buzz!") diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 4e318d26fed..7c5fe09dd06 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -16,7 +16,9 @@ var/Mtoollink = 0 // variable to decide if an object should show the multitool menu linking menu, not all objects use it - + var/burn_state = FIRE_PROOF // LAVA_PROOF | FIRE_PROOF | FLAMMABLE | ON_FIRE + var/burntime = 10 //How long it takes to burn to ashes, in seconds + var/burn_world_time //What world time the object will burn up completely var/being_shocked = 0 var/on_blueprints = FALSE //Are we visible on the station blueprints at roundstart? @@ -288,4 +290,32 @@ a { being_shocked = 0 /obj/proc/CanAStarPass() - . = !density \ No newline at end of file + . = !density + +/obj/fire_act(global_overlay=1) + if(!burn_state) + burn_state = ON_FIRE + fire_master.burning += src + burn_world_time = world.time + burntime*rand(10,20) + if(global_overlay) + overlays += fire_overlay + return 1 + +/obj/proc/burn() + empty_object_contents(1, loc) + var/obj/effect/decal/cleanable/ash/A = new(loc) + A.desc = "Looks like this used to be a [name] some time ago." + fire_master.burning -= src + qdel(src) + +/obj/proc/extinguish() + if(burn_state == ON_FIRE) + burn_state = FLAMMABLE + overlays -= fire_overlay + fire_master.burning -= src + +/obj/proc/empty_object_contents(burn = 0, new_loc = loc) + for(var/obj/item/Item in contents) //Empty out the contents + Item.forceMove(new_loc) + if(burn) + Item.fire_act() //Set them on fire, too \ No newline at end of file diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 9251890dc6e..045f58d577d 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -15,6 +15,8 @@ icon = 'icons/obj/artstuff.dmi' icon_state = "easel" density = 1 + burn_state = FLAMMABLE + burntime = 15 var/obj/item/weapon/canvas/painting = null @@ -56,6 +58,7 @@ var/global/list/globalBlankCanvases[AMT_OF_CANVASES] desc = "Draw out your soul on this canvas! Only crayons can draw on it. Examine it to focus on the canvas." icon = 'icons/obj/artstuff.dmi' icon_state = "11x11" + burn_state = FLAMMABLE var/whichGlobalBackup = 1 //List index /obj/item/weapon/canvas/nineteenXnineteen diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 31958409954..10f09401ba5 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -16,6 +16,7 @@ LINEN BINS throw_range = 2 w_class = 1 item_color = "white" + burn_state = FLAMMABLE slot_flags = SLOT_BACK @@ -161,6 +162,8 @@ LINEN BINS icon = 'icons/obj/structures.dmi' icon_state = "linenbin-full" anchored = 1 + burn_state = FLAMMABLE + burntime = 20 var/amount = 20 var/list/sheets = list() var/obj/item/hidden = null @@ -184,6 +187,16 @@ LINEN BINS else icon_state = "linenbin-full" +/obj/structure/bedsheetbin/fire_act() + if(!amount) + return + ..() + +/obj/structure/bedsheetbin/burn() + amount = 0 + extinguish() + update_icon() + /obj/structure/bedsheetbin/attackby(obj/item/I as obj, mob/user as mob, params) if(istype(I, /obj/item/weapon/bedsheet)) user.drop_item() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index de0ef28d255..4fe639160d4 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -192,6 +192,7 @@ return var/obj/item/weapon/rcs/E = W if(E.rcell && (E.rcell.charge >= E.chargecost)) + // TODO: Tie into space manager if(!(src.z in config.contact_levels)) to_chat(user, "The rapid-crate-sender can't locate any telepads!") return diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 45c2f538e26..e859c0348f1 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -5,6 +5,8 @@ icon_opened = "cardboard_open" icon_closed = "cardboard" health = 10 + burn_state = FLAMMABLE + burntime = 20 sound = 'sound/effects/rustle2.ogg' material_drop = /obj/item/stack/sheet/cardboard cutting_sound = 'sound/items/poster_ripped.ogg' diff --git a/code/game/objects/structures/crates_lockers/closets/coffin.dm b/code/game/objects/structures/crates_lockers/closets/coffin.dm index 03337e6a260..6e34e70894e 100644 --- a/code/game/objects/structures/crates_lockers/closets/coffin.dm +++ b/code/game/objects/structures/crates_lockers/closets/coffin.dm @@ -4,6 +4,9 @@ icon_state = "coffin" icon_closed = "coffin" icon_opened = "coffin_open" + burn_state = FLAMMABLE + burntime = 20 + material_drop = /obj/item/stack/sheet/wood /obj/structure/closet/coffin/update_icon() if(!opened) @@ -16,4 +19,5 @@ icon_state = "sarc" icon_closed = "sarc" icon_opened = "sarc_open" - sound = 'sound/effects/stonedoor_openclose.ogg' \ No newline at end of file + sound = 'sound/effects/stonedoor_openclose.ogg' + material_drop = /obj/item/stack/sheet/mineral/sandstone \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index bff3228dbc9..169179ca375 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -4,6 +4,8 @@ icon_state = "cabinet_closed" icon_closed = "cabinet_closed" icon_opened = "cabinet_open" + burn_state = FLAMMABLE + burntime = 20 /obj/structure/closet/cabinet/update_icon() if(!opened) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/bar.dm b/code/game/objects/structures/crates_lockers/closets/secure/bar.dm index af6424571ca..49006fb7fb5 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/bar.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/bar.dm @@ -7,6 +7,8 @@ icon_opened = "cabinetdetective_open" icon_broken = "cabinetdetective_broken" icon_off = "cabinetdetective_broken" + burn_state = FLAMMABLE + burntime = 20 New() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 7c880918e41..d130b22074c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -117,12 +117,12 @@ /obj/structure/closet/secure_closet/atmos_personal name = "technician's locker" req_access = list(access_atmospherics) - icon_state = "secureeng1" - icon_closed = "secureeng" - icon_locked = "secureeng1" - icon_opened = "secureengopen" - icon_broken = "secureengbroken" - icon_off = "secureengoff" + icon_state = "secureatm1" + icon_closed = "secureatm" + icon_locked = "secureatm1" + icon_opened = "secureatmopen" + icon_broken = "secureatmbroken" + icon_off = "secureatmoff" New() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index 51e3e8d06c3..7eab1e6de85 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -33,6 +33,8 @@ icon_opened = "cabinetdetective_open" icon_broken = "cabinetdetective_broken" icon_off = "cabinetdetective_broken" + burn_state = FLAMMABLE + burntime = 20 /obj/structure/closet/secure_closet/personal/cabinet/update_icon() if(broken) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 66c470882c8..93d200e020d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -317,6 +317,8 @@ icon_opened = "cabinetdetective_open" icon_broken = "cabinetdetective_broken" icon_off = "cabinetdetective_broken" + burn_state = FLAMMABLE + burntime = 20 New() ..() @@ -339,6 +341,7 @@ new /obj/item/clothing/accessory/holster/armpit(src) new /obj/item/clothing/glasses/sunglasses/yeah(src) new /obj/item/device/flashlight/seclite(src) + new /obj/item/clothing/accessory/black(src) /obj/structure/closet/secure_closet/detective/update_icon() if(broken) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index c23701575df..d651ad55adb 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -168,8 +168,8 @@ /obj/structure/closet/wardrobe/atmospherics_yellow name = "atmospherics wardrobe" - icon_state = "yellow" - icon_closed = "yellow" + icon_state = "atmostech" + icon_closed = "atmostech" /obj/structure/closet/wardrobe/atmospherics_yellow/New() ..() @@ -193,8 +193,8 @@ /obj/structure/closet/wardrobe/engineering_yellow name = "engineering wardrobe" - icon_state = "yellow" - icon_closed = "yellow" + icon_state = "engineer" + icon_closed = "engineer" /obj/structure/closet/wardrobe/engineering_yellow/New() ..() diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index c4178baec15..f9b32b071f7 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -84,6 +84,7 @@ if(istype(W, /obj/item/weapon/rcs) && !src.opened) var/obj/item/weapon/rcs/E = W if(E.rcell && (E.rcell.charge >= E.chargecost)) + // TODO: Tie into space manager if(!(src.z in config.player_levels)) to_chat(user, "The rapid-crate-sender can't locate any telepads!") return diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm index f5ab3cb14aa..7719f9b547d 100644 --- a/code/game/objects/structures/electricchair.dm +++ b/code/game/objects/structures/electricchair.dm @@ -77,13 +77,10 @@ s.start() visible_message("The electric chair went off!", "You hear a deep sharp shock!") if(buckled_mob) - buckled_mob.burn_skin(90) + buckled_mob.electrocute_act(110, src, 1) to_chat(buckled_mob, "You feel a deep shock course through your body!") - sleep(1) - buckled_mob.burn_skin(90) - sleep(5) - buckled_mob.burn_skin(max(rand(5,20),rand(5,20),rand(5,20))) - + spawn(1) + buckled_mob.electrocute_act(110, src, 1) A.power_light = light A.updateicon() return diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index e4f8acd2c5b..23c6e096748 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -1,3 +1,7 @@ +/obj/structure/flora + burn_state = FLAMMABLE + burntime = 30 + //trees /obj/structure/flora/tree name = "tree" @@ -230,6 +234,7 @@ desc = "a rock" icon_state = "rock1" icon = 'icons/obj/flora/rocks.dmi' + burn_state = FIRE_PROOF anchored = 1 /obj/structure/flora/rock/New() diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 9ce9e59e423..b9af7b2d032 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -219,6 +219,8 @@ /obj/structure/mineral_door/wood mineralType = "wood" hardness = 1 + burn_state = FLAMMABLE + burntime = 30 Open() isSwitchingStates = 1 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 71a0c8379a9..cf5c97ed593 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -361,6 +361,8 @@ user.attack_log +="\[[time_stamp()]\] Cremated [M.name] ([M.ckey])" log_attack("[user.name] ([user.ckey]) cremated [M.name] ([M.ckey])") M.death(1) + if(!M || !isnull(M.gcDestroyed)) + continue // Re-check for mobs that delete themselves on death M.ghostize() qdel(M) diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 24ea6b5a358..bfb5d584965 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -41,6 +41,7 @@ desc = "" icon = 'icons/obj/decals.dmi' w_class = 3 //big + burn_state = FLAMMABLE var/sign_state = "" /obj/item/sign/attackby(obj/item/tool as obj, mob/user as mob) //construction diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index f13bffb9d44..c5a3b2f15ba 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -13,6 +13,8 @@ icon_state = "bed" can_buckle = 1 buckle_lying = 1 + burn_state = FLAMMABLE + burntime = 30 var/movable = 0 // For mobility checks /obj/structure/stool/bed/MouseDrop(atom/over_object) @@ -46,6 +48,7 @@ name = "roller bed" icon = 'icons/obj/rollerbed.dmi' icon_state = "down" + burn_state = FIRE_PROOF anchored = 0 /obj/structure/stool/bed/roller/attackby(obj/item/weapon/W as obj, mob/user as mob, params) diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index a12f804d308..1c3c3f8e793 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -3,6 +3,7 @@ desc = "You sit in this. Either by will or force." icon_state = "chair" buckle_lying = 0 //you sit in a chair, not lay + burn_state = FIRE_PROOF var/propelled = 0 // Check for fire-extinguisher-driven chairs @@ -76,6 +77,8 @@ // Chair types /obj/structure/stool/bed/chair/wood + burn_state = FLAMMABLE + burntime = 20 // TODO: Special ash subtype that looks like charred chair legs /obj/structure/stool/bed/chair/wood/normal @@ -103,6 +106,8 @@ desc = "It looks comfy." icon_state = "comfychair" color = rgb(255,255,255) + burn_state = FLAMMABLE + burntime = 30 var/image/armrest = null /obj/structure/stool/bed/chair/comfy/New() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 285b1da8aa5..48193933a66 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -369,6 +369,8 @@ parts = /obj/item/weapon/table_parts/wood health = 50 canSmoothWith = list(/obj/structure/table/woodentable, /obj/structure/table/woodentable/poker) + burn_state = FLAMMABLE + burntime = 20 var/canPokerize = 1 /obj/structure/table/woodentable/attackby(obj/item/I as obj, mob/user as mob, params) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 5d8c98be329..b27d3f6e4f8 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -249,12 +249,16 @@ /obj/machinery/shower/proc/wash(atom/movable/O as obj|mob) if(!on) return + if(istype(O, /obj/item)) + var/obj/item/I = O + I.extinguish() + O.water_act(100, convertHeat(), src) if(isliving(O)) var/mob/living/L = O L.ExtinguishMob() - L.fire_stacks = -20 //Douse ourselves with water to avoid fire more easily + L.adjust_fire_stacks(-20) //Douse ourselves with water to avoid fire more easily to_chat(L, "You've been drenched in water!") if(iscarbon(O)) var/mob/living/carbon/M = O diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 7ae2ddcd27d..051dbe55495 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -425,11 +425,6 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f hit(round(exposed_volume / 1000), 0) ..() -/obj/structure/window/plasmabasic/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 32000) - hit(round(exposed_volume / 1000), 0) - ..() - /obj/structure/window/plasmabasic/BlockSuperconductivity() return 1 @@ -457,9 +452,6 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f /obj/structure/window/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) return -/obj/structure/window/plasmareinforced/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - /obj/structure/window/plasmareinforced/BlockSuperconductivity() return 1 //okay this SHOULD MAKE THE TOXINS CHAMBER WORK diff --git a/code/game/response_team.dm b/code/game/response_team.dm index abd4f0fcffa..abda62f9420 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -114,13 +114,17 @@ var/ert_request_answered = 0 active_team = response_team_type send_emergency_team = 1 - var/list/ert_candidates = pollCandidates("Join the Emergency Response Team?",, responseteam_age, 600) + var/list/ert_candidates = pollCandidates("Join the Emergency Response Team?",, responseteam_age, 600, 1) if(!ert_candidates.len) active_team.cannot_send_team() send_emergency_team = 0 return var/teamsize = 0 - for(var/mob/dead/observer/M in ert_candidates) + // Respawnable players get first dibs + for(var/mob/dead/observer/M in (ert_candidates & respawnable_list)) + teamsize += M.JoinResponseTeam() + // If there's still open slots, non-respawnable players can fill them + for(var/mob/dead/observer/M in (ert_candidates - respawnable_list)) teamsize += M.JoinResponseTeam() send_emergency_team = 0 if (!teamsize) @@ -422,7 +426,7 @@ var/ert_request_answered = 0 switch(officer_type) if("Engineer") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/engineer(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/engi(M), slot_s_store) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/meson(M), slot_glasses) @@ -442,7 +446,7 @@ var/ert_request_answered = 0 if("Security") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/security(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun/advtaser(M), slot_s_store) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) @@ -460,7 +464,7 @@ var/ert_request_answered = 0 if("Medic") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/latex/nitrile(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/medical(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health/health_advanced(M), slot_glasses) @@ -479,7 +483,7 @@ var/ert_request_answered = 0 if("Commander") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/commander(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) @@ -507,7 +511,7 @@ var/ert_request_answered = 0 switch(officer_type) if("Engineer") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/advance(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/engineer(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double/full(M), slot_s_store) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/meson/night(M), slot_glasses) diff --git a/code/game/sound.dm b/code/game/sound.dm index 7bf3af10e9c..fe5e361f16a 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -25,25 +25,26 @@ var/list/ricochet = list('sound/weapons/effects/ric1.ogg', 'sound/weapons/effect var/turf/turf_source = get_turf(source) // Looping through the player list has the added bonus of working for mobs inside containers + var/sound/S = sound(soundin) + var/maxdistance = (world.view + extrarange) * 3 for(var/P in player_list) var/mob/M = P if(!M || !M.client) continue - var/distance = get_dist(M, turf_source) - if(distance <= (world.view + extrarange) * 3) + + if(distance <= maxdistance) var/turf/T = get_turf(M) if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, S) -var/const/FALLOFF_SOUNDS = 0.5 +/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, sound/S) + if(!src.client || ear_deaf > 0) + return -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global) - if(!src.client || ear_deaf > 0) return - soundin = get_sfx(soundin) - - var/sound/S = sound(soundin) + if(!S) + S = sound(get_sfx(soundin)) S.wait = 0 //No queue S.channel = 0 //Any channel S.volume = vol diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 3c73c0789e7..b8a6635225a 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -80,17 +80,6 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," src.hotspot_expose(1000,CELL_VOLUME) return -/turf/simulated/floor/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(!burnt && prob(5)) - burn_tile() - -/turf/simulated/floor/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) - var/dir_to = get_dir(src, adj_turf) - - for(var/obj/structure/window/W in src) - if(W.dir == dir_to || W.is_fulltile()) //Same direction or diagonal (full tile) - W.fire_act(adj_air, adj_temp, adj_volume) - /turf/simulated/floor/is_shielded() for(var/obj/structure/A in contents) if(A.level == 3) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 4d7c8ccd5da..547efaed2a6 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -32,7 +32,8 @@ /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/simulated/wall/rust, - /turf/simulated/wall/r_wall/rust) + /turf/simulated/wall/r_wall/rust, + /turf/simulated/wall/r_wall/coated) smooth = SMOOTH_TRUE /turf/simulated/wall/ChangeTurf(var/newtype) @@ -110,13 +111,11 @@ update_icon() return -/* -/turf/simulated/wall/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) - if(adj_temp > max_temperature) - take_damage(rand(10, 20) * (adj_temp / max_temperature)) - return ..() -*/ +/turf/simulated/wall/proc/adjacent_fire_act(turf/simulated/wall, radiated_temperature) + if(radiated_temperature > max_temperature) + take_damage(rand(10, 20) * (radiated_temperature / max_temperature)) + /turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0) if(istype(src,/turf/simulated/wall/r_wall)) if(!devastated) diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm index 3d65d97c95b..6d59513e761 100644 --- a/code/game/turfs/simulated/walls_misc.dm +++ b/code/game/turfs/simulated/walls_misc.dm @@ -21,4 +21,9 @@ desc = "A huge chunk of rusted reinforced metal." icon = 'icons/turf/walls/rusty_reinforced_wall.dmi' icon_state = "rrust" - walltype = "rrust" \ No newline at end of file + walltype = "rrust" + +/turf/simulated/wall/r_wall/coated //Coated for heat resistance + name = "coated reinforced wall" + desc = "A huge chunk of reinforced metal used to seperate rooms. It seems to have additional plating to protect against heat." + max_temperature = INFINITY \ No newline at end of file diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 27154fd00fb..7c6c750c70e 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -12,6 +12,7 @@ walltype = "rwall" var/d_state = 0 + var/can_be_reinforced = 1 /turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob, params) user.changeNext_move(CLICK_CD_MELEE) @@ -229,6 +230,24 @@ smooth_icon_neighbors(src) to_chat(user, "You repair the last of the damage.") + //UPGRADING TO COATED + else if(istype(W, /obj/item/stack/sheet/plasteel) && !d_state) + var/obj/item/stack/sheet/plasteel/MS = W + if(!can_be_reinforced) + to_chat(user, "The wall is already coated!") + return + to_chat(user, "You begin adding an additional layer of coating to the wall with \a [MS].") + + if(do_after(user, 40, target = src) && !d_state) + if(!MS.use(2)) + to_chat(user, "You don't have enough plasteel for that!") + return + to_chat(user, "You add an additional layer of coating to the wall!") + ChangeTurf(/turf/simulated/wall/r_wall/coated) + update_icon() + smooth_icon_neighbors(src) + can_be_reinforced = 0 + return //APC else if(istype(W,/obj/item/mounted)) @@ -293,4 +312,5 @@ clear_smooth_overlays() else smooth = SMOOTH_TRUE - icon_state = "" \ No newline at end of file + icon_state = "" + diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d76791e7f97..93b9c339652 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -135,9 +135,6 @@ loopsanity-- A.HasProximity(M, 1) -/turf/proc/adjacent_fire_act(turf/simulated/floor/source, temperature, volume) - return - /turf/proc/levelupdate() for(var/obj/O in src) if(O.level == 1) @@ -166,6 +163,7 @@ var/list/old_affecting_lights = affecting_lights var/old_lighting_overlay = lighting_overlay var/old_blueprint_data = blueprint_data + var/old_obscured = obscured if(air_master) air_master.remove_from_active(src) @@ -188,6 +186,8 @@ lighting_build_overlays() else lighting_clear_overlays() + + obscured = old_obscured return W diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 894fc07bd60..fa452446e87 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -114,7 +114,8 @@ var/list/admin_verbs_event = list( var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ - /client/proc/respawn_character + /client/proc/respawn_character, + /client/proc/admin_deserialize ) var/list/admin_verbs_server = list( /client/proc/ToRban, @@ -152,8 +153,6 @@ var/list/admin_verbs_debug = list( /client/proc/toggledebuglogs, /client/proc/qdel_toggle, /client/proc/gc_dump_hdl, - /client/proc/gc_toggle_profiling, - /client/proc/gc_show_del_report, /client/proc/debugNatureMapGenerator, /client/proc/check_bomb_impacts, /client/proc/test_movable_UI, @@ -162,7 +161,9 @@ var/list/admin_verbs_debug = list( /proc/machine_upgrade, /client/proc/map_template_load, /client/proc/map_template_upload, - /client/proc/view_runtimes + /client/proc/view_runtimes, + /client/proc/admin_serialize, + /client/proc/admin_deserialize ) var/list/admin_verbs_possess = list( /proc/possess, diff --git a/code/modules/admin/buildmode.dm b/code/modules/admin/buildmode.dm index db97d7eb5ec..f08121634d3 100644 --- a/code/modules/admin/buildmode.dm +++ b/code/modules/admin/buildmode.dm @@ -8,7 +8,8 @@ #define FILL_BUILDMODE 8 #define LINK_BUILDMODE 9 #define BOOM_BUILDMODE 10 -#define NUM_BUILDMODES 10 +#define SAVE_BUILDMODE 11 +#define NUM_BUILDMODES 11 /obj/screen/buildmode icon = 'icons/misc/buildmode.dmi' @@ -81,8 +82,11 @@ /obj/effect/buildmode_reticule/New(var/turf/t, var/client/c) loc = t I = image('icons/mob/blob.dmi', t, "marker",19.0,2) // Sprite reuse wooo - cl = c - cl.images += I + if(c) + cl = c + cl.images += I + else + log_debug("Buildmode reticule created without a client!") /obj/effect/buildmode_reticule/proc/deselect() qdel(src) @@ -174,6 +178,8 @@ var/light = -1 var/flash = -1 var/flames = -1 + // Saving mode + var/use_json = TRUE /datum/click_intercept/buildmode/New(client/c) ..() @@ -261,6 +267,13 @@ to_chat(user, "***********************************************************") to_chat(user, "Mouse Button on obj = Kaboom") to_chat(user, "***********************************************************") + if(SAVE_BUILDMODE) + to_chat(user, "***********************************************************") + to_chat(user, "Left Mouse Button on turf/obj/mob = Select corner") + to_chat(user, "***********************************************************") + + + /datum/click_intercept/buildmode/proc/change_settings(mob/user) switch(mode) @@ -345,6 +358,9 @@ var/flames = input("Range of flames. -1 to none", text("Input")) as num|null if(flames == null) flames = -1 + if(SAVE_BUILDMODE) + use_json = (alert("Would you like to use json (Default is \"Yes\")?",,"Yes","No") == "Yes") + /datum/click_intercept/buildmode/proc/change_dir() switch(build_dir) if(NORTH) @@ -613,7 +629,7 @@ var/obj/effect/buildmode_line/L2 = new(holder, P, M, "[M.name] to [P.name]") // Yes, reversed one so that you can see it from both sides. L2.color = L.color link_lines += L2 - for(var/obj/machinery/door/poddoor/P in world) + for(var/obj/machinery/door/poddoor/P in airlocks) if(P.id_tag == M.id) var/obj/effect/buildmode_line/L = new(holder, M, P, "[M.name] to [P.name]") L.color = M.normaldoorcontrol ? "#993333" : "#339933" @@ -625,3 +641,27 @@ link_lines += L2 if(BOOM_BUILDMODE) explosion(object, devastation, heavy, light, flash, null, null,flames) + if(SAVE_BUILDMODE) + if(!cornerA) + cornerA = select_tile(get_turf(object)) + return + if(!cornerB) + cornerB = select_tile(get_turf(object)) + if(left_click) + if(cornerA && cornerB) + var/turf/A = get_turf(cornerA) + var/turf/B = get_turf(cornerB) + deselect_region() // So we don't read our own reticules + var/map_name = input(holder, "Please select a name for your map", "Buildmode", "") + if(map_name == "") + return + var/map_flags = 0 + if(use_json) + map_flags = 32 // Magic number defined in `writer.dm` that I can't use directly + // because #defines are for some reason our coding standard + var/our_map = maploader.save_map(A,B,map_name,map_flags) + holder << ftp(our_map) // send the map they've made! Or are stealing, whatever + to_chat(holder, "Map saving complete! [our_map]") + return + + deselect_region() diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 3849317b03e..7ee714090cc 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -24,6 +24,10 @@ var/list/admin_datums = list() rights = initial_rights admin_datums[ckey] = src +/datum/admins/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + /datum/admins/proc/associate(client/C) if(istype(C)) owner = C @@ -85,7 +89,7 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself. admin_datums -= ckey if(holder) holder.disassociate() - del(holder) + qdel(holder) return 1 //This proc checks whether subject has at least ONE of the rights specified in rights_required. diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index e2b6ab56d62..929e224494c 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -38,13 +38,7 @@ Make all areas powered   Make all areas unpowered   Power all SMES
    -
    - Shuttle options
    - Launch a shuttle   - Force launch a shuttle
    - Jump a shuttle   - Move a shuttle
    -
    + "} else if(check_rights(R_SERVER,0)) //only add this if admin secrets are unavailiable; otherwise, it's added inline @@ -73,7 +67,7 @@

    IC Events

    Teams
    - Send in a strike team   + Send in the Deathsquad   Send in a syndicate strike team   Send in a HONKsquad
    Change Security Level
    diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a7fc809aa88..252636abcda 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1252,6 +1252,7 @@ message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] back to the Lobby.") var/mob/new_player/NP = new() + non_respawnable_keys -= M.ckey NP.ckey = M.ckey qdel(M) @@ -1565,53 +1566,7 @@ else if(href_list["adminmoreinfo"]) var/mob/M = locate(href_list["adminmoreinfo"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - var/location_description = "" - var/special_role_description = "" - var/health_description = "" - var/gender_description = "" - var/turf/T = get_turf(M) - - //Location - if(isturf(T)) - if(isarea(T.loc)) - location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])" - else - location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])" - - //Job + antagonist - if(M.mind) - special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]" - else - special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;" - - //Health - if(isliving(M)) - var/mob/living/L = M - var/status - switch(M.stat) - if(0) status = "Alive" - if(1) status = "Unconscious" - if(2) status = "Dead" - health_description = "Status = [status]" - health_description += "
    Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]" - else - health_description = "This mob type has no health to speak of." - - //Gener - switch(M.gender) - if(MALE,FEMALE) gender_description = "[M.gender]" - else gender_description = "[M.gender]" - - to_chat(src.owner, "Info about [M.name]: ") - to_chat(src.owner, "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]") - to_chat(src.owner, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];") - to_chat(src.owner, "Location = [location_description];") - to_chat(src.owner, "[special_role_description]") - to_chat(src.owner, "(PM) (PP) (VV) (SM) (FLW) (CA)") + admin_mob_info(M) else if(href_list["adminspawncookie"]) if(!check_rights(R_ADMIN|R_EVENT)) return @@ -2025,6 +1980,7 @@ return else for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + // TODO: Tie into space manager if((F.z in config.station_levels)) spawn(0) if(!F.receivefax(P)) @@ -2372,6 +2328,7 @@ for(var/mob/living/carbon/human/H in mob_list) var/turf/loc = find_loc(H) var/security = 0 + // TODO: Tie into space manager if(!(loc.z in config.station_levels) || prisonwarped.Find(H)) //don't warp them if they aren't ready or are already there @@ -2608,7 +2565,8 @@ if("eagles")//SCRAW feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","EgL") - for(var/obj/machinery/door/airlock/W in world) + for(var/obj/machinery/door/airlock/W in airlocks) + // TODO: Tie into space manager if((W.z in config.station_levels) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) W.req_access = list() message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") @@ -2801,12 +2759,12 @@ dat += "No-one has done anything this round!" usr << browse(dat, "window=admin_log") if("maint_access_brig") - for(var/obj/machinery/door/airlock/maintenance/M in world) + for(var/obj/machinery/door/airlock/maintenance/M in airlocks) if(access_maint_tunnels in M.req_access) M.req_access = list(access_brig) message_admins("[key_name_admin(usr)] made all maint doors brig access-only.") if("maint_access_engiebrig") - for(var/obj/machinery/door/airlock/maintenance/M in world) + for(var/obj/machinery/door/airlock/maintenance/M in airlocks) if(access_maint_tunnels in M.req_access) M.req_access = list() M.req_one_access = list(access_brig,access_engine) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 27048b441dd..e07bda7c8ee 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -89,7 +89,7 @@ if("delete") for(var/datum/d in objs) - del(d) + qdel(d) if("select") var/text = "" diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 1cc723ab903..2c930080edc 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -373,6 +373,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that for(var/I in singularities) var/obj/singularity/S = I + // TODO: Tie into space manager if(S.z == ZLEVEL_CENTCOMM || S.z >= MAX_Z) continue qdel(S) @@ -593,17 +594,25 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that "tournament janitor", "pirate", "space pirate", + "soviet tourist", + "soviet soldier", "soviet admiral", "tunnel clown", + "mime assassin", "survivor", + "greytide", + "greytide leader", + "greytide xeno", "masked killer", "singuloth knight", "dark lord", "assassin", "spy", + "vox", "death commando", "syndicate agent", "syndicate operative", + "syndicate bomber", "syndicate strike team", "syndicate officer", "chrono legionnaire", @@ -728,7 +737,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) var/obj/item/weapon/storage/backpack/backpack = new(M) for(var/obj/item/I in backpack) - del(I) + qdel(I) M.equip_to_slot_or_del(backpack, slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/mop(M), slot_r_hand) var/obj/item/weapon/reagent_containers/glass/bucket/bucket = new(M) @@ -746,30 +755,29 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if("pirate") M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/head/bandana(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) - equip_special_id(M,get_all_accesses(), "Pirate", /obj/item/weapon/card/id) + equip_special_id(M,list(access_maint_tunnels), "Pirate", /obj/item/weapon/card/id) - if("space pirate") + if("space pirate") // not spaceworthy, just has fancier coat. M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/pirate(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/pirate(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) - equip_special_id(M,get_all_accesses(), "Space Pirate", /obj/item/weapon/card/id) - - if("soviet soldier") - M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/head/ushanka(M), slot_head) - equip_special_id(M,get_all_accesses(), "Soviet Soldier", /obj/item/weapon/card/id) + equip_special_id(M,list(access_maint_tunnels), "Space Pirate", /obj/item/weapon/card/id) if("tunnel clown") M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) @@ -780,25 +788,106 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/suit/chaplain_hoodie(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_r_store) - equip_special_id(M,get_all_accesses(), "Tunnel Clown", /obj/item/weapon/card/id) + equip_special_id(M,list(access_clown, access_theatre, access_maint_tunnels), "Tunnel Clown", /obj/item/weapon/card/id) M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) M.equip_to_slot_or_del(fire_axe, slot_r_hand) + + if("mime assassin") + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/mime(M), slot_back) + if(M.gender == FEMALE) + M.equip_or_collect(new /obj/item/clothing/under/sexymime(M), slot_w_uniform) + M.equip_or_collect(new /obj/item/clothing/mask/gas/sexymime(M), slot_wear_mask) + else + M.equip_or_collect(new /obj/item/clothing/under/mime(M), slot_w_uniform) + M.equip_or_collect(new /obj/item/clothing/mask/gas/mime(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/head/beret(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full/multitool(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/syndie_kit/caneshotgun, slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/toy/crayon/mime, slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/pistol(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/suppressor(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/pen/sleepy(M), slot_in_backpack) + M.equip_or_collect(new /obj/item/weapon/reagent_containers/food/snacks/syndidonkpocket(M), slot_in_backpack) + var/obj/item/device/pda/mime/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Mime" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_wear_pda) + equip_special_id(M,list(access_mime, access_theatre, access_maint_tunnels), "Mime", /obj/item/weapon/card/id/syndicate) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) + if("survivor") M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/latex(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - equip_special_id(M,get_all_accesses(), "Survivor", /obj/item/weapon/card/id) + equip_special_id(M,list(access_maint_tunnels), "Survivor", /obj/item/weapon/card/id) for(var/obj/item/carried_item in M.contents) if(!istype(carried_item, /obj/item/weapon/implant)) carried_item.add_blood(M) + if("greytide") + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/flag/grey(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) + equip_special_id(M,list(access_maint_tunnels), "Greytide", /obj/item/weapon/card/id) + + if("greytide leader") + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/flag/grey(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full/multitool(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) + equip_special_id(M,list(access_maint_tunnels), "Greytide Leader", /obj/item/weapon/card/id) + + if("greytide xeno") + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/xenos(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/xenos(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double/full(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/toy/toy_xeno(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full/multitool(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) + equip_special_id(M,list(access_maint_tunnels), "Legit Xenomorph", /obj/item/weapon/card/id) + if("masked killer") M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/latex(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask) @@ -809,7 +898,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/kitchen/knife(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/scalpel(M), slot_r_store) M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) - equip_special_id(M,get_all_accesses(), "Masked Killer", /obj/item/weapon/card/id/syndicate, "syndie") + equip_special_id(M,list(access_maint_tunnels), "Masked Killer", /obj/item/weapon/card/id/syndicate, "syndie") var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) M.equip_to_slot_or_del(fire_axe, slot_r_hand) for(var/obj/item/carried_item in M.contents) @@ -821,6 +910,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/device/radio/headset/syndicate(M), slot_l_ear) M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/dualsaber/red(M), slot_l_hand) @@ -841,6 +931,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/saber(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = new(M) for(var/obj/item/briefcase_item in sec_briefcase) @@ -880,14 +971,39 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/pen/sleepy(M), slot_r_store) var/obj/item/weapon/implant/dust/DUST = new /obj/item/weapon/implant/dust(M) DUST.implant(M) - var/obj/item/weapon/implant/dust/STOR = new /obj/item/weapon/implant/storage(M) - STOR.implant(M) + M.equip_to_slot_or_del(new /obj/item/weapon/implanter/storage(M), slot_in_backpack) var/obj/item/device/pda/heads/pda = new(M) pda.owner = M.real_name pda.ownjob = "Spy" pda.name = "PDA-[M.real_name] ([pda.ownjob])" M.equip_to_slot_or_del(pda, slot_belt) - equip_special_id(M,get_all_accesses(), "Spy", /obj/item/weapon/card/id/syndicate, "syndie") + equip_special_id(M,list(access_maint_tunnels), "Spy", /obj/item/weapon/card/id/syndicate, "syndie") + + + if("vox") + if(istype(M, /mob/living/carbon/human/voxarmalis)) // have to do this, they cannot wear normal vox gear! + M.equip_to_slot_or_del(new /obj/item/clothing/under/vox_grey(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/under/vox/vox_robes (M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate/vox(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/syndicate, slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow/vox, slot_gloves) + M.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic, slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/vox, slot_r_store) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle, slot_glasses) + M.equip_to_slot_or_del(new /obj/item/device/flashlight, slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/restraints/handcuffs/cable/zipties, slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/flash, slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/noisecannon, slot_in_backpack) + equip_special_id(M,get_all_accesses(), "Vox Armalis", /obj/item/weapon/card/id/syndicate/vox, "syndie") + else + M.equip_vox_raider() + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_l_hand) + M.regenerate_icons() if("death commando") M.equip_death_commando() @@ -909,15 +1025,31 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that U.hidden_uplink.uses = 20 M.equip_to_slot_or_del(U, slot_r_store) + if("syndicate bomber") + M.equip_or_collect(new /obj/item/clothing/under/syndicate(M), slot_w_uniform) + M.equip_or_collect(new /obj/item/clothing/shoes/combat(M), slot_shoes) + M.equip_or_collect(new /obj/item/clothing/gloves/combat(M), slot_gloves) + M.equip_or_collect(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) + M.equip_or_collect(new /obj/item/device/flashlight(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/card/emag(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/radio/beacon/syndicate/bomb(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/radio/beacon/syndicate/bomb(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/syndicatedetonator(M), slot_in_backpack) + M.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full/multitool(M), slot_belt) + M.equip_or_collect(new /obj/item/weapon/reagent_containers/food/snacks/syndidonkpocket(M), slot_in_backpack) + M.equip_or_collect(new /obj/item/device/radio/headset/syndicate(M), slot_l_ear) + equip_special_id(M,get_syndicate_access("Syndicate Operative"), "Syndicate Bomber", /obj/item/weapon/card/id/syndicate, "syndie") + if("syndicate operative") M.equip_or_collect(new /obj/item/clothing/under/syndicate(M), slot_w_uniform) M.equip_or_collect(new /obj/item/clothing/shoes/combat(M), slot_shoes) M.equip_or_collect(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_or_collect(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/reagent_containers/food/pill/initropidril(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/gun/projectile/automatic/pistol(M), slot_in_backpack) M.equip_or_collect(new /obj/item/ammo_box/magazine/m10mm(M), slot_in_backpack) - M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/crowbar/red(M), slot_in_backpack) M.equip_or_collect(new /obj/item/clothing/glasses/night(M), slot_glasses) M.equip_or_collect(new /obj/item/weapon/storage/belt/military(M), slot_belt) @@ -948,8 +1080,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(new /obj/item/clothing/shoes/combat(M), slot_shoes) M.equip_or_collect(new /obj/item/clothing/gloves/combat(M), slot_gloves) M.equip_or_collect(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_or_collect(new /obj/item/weapon/reagent_containers/food/pill/initropidril(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) + M.equip_or_collect(new /obj/item/weapon/reagent_containers/food/pill/initropidril(M), slot_in_backpack) M.equip_or_collect(new /obj/item/clothing/glasses/thermal(M), slot_glasses) M.equip_or_collect(new /obj/item/weapon/storage/belt/military(M), slot_belt) M.equip_or_collect(new /obj/item/weapon/pinpointer/advpinpointer(M), slot_l_store) @@ -974,6 +1106,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(new /obj/item/clothing/shoes/black(M), slot_shoes) M.equip_or_collect(new /obj/item/clothing/gloves/color/black(M), slot_gloves) M.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_or_collect(new /obj/item/clothing/head/that(M), slot_head) M.equip_or_collect(new /obj/item/device/radio/headset/ert(M), slot_l_ear) M.equip_or_collect(new /obj/item/device/pda/(M), slot_wear_pda) @@ -989,6 +1122,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_belt) M.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/implanter/dust(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/implanter/death_alarm(M), slot_in_backpack) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(M) @@ -1007,6 +1141,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_belt) M.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/implanter/dust(M), slot_in_backpack) M.equip_or_collect(new /obj/item/weapon/implanter/death_alarm(M), slot_in_backpack) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(M) @@ -1051,6 +1186,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/cyber(M), slot_glasses) // job has /obj/item/clothing/glasses/hud/security/sunglasses M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol/m1911(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/deathsquad/officer(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double/full(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/implanter/dust(M), slot_in_backpack) @@ -1078,6 +1214,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol/m1911(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/cohiba(M), slot_wear_mask) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_or_collect(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/matches(M), slot_r_store) M.equip_or_collect(new /obj/item/weapon/melee/classic_baton/telescopic(M), slot_in_backpack) @@ -1117,7 +1254,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/staff(M), slot_l_hand) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) equip_special_id(M,get_all_accesses(), "Wizard", /obj/item/weapon/card/id) if("red wizard") @@ -1130,7 +1267,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/staff(M), slot_l_hand) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) equip_special_id(M,get_all_accesses(), "Wizard", /obj/item/weapon/card/id) if("marisa wizard") @@ -1143,20 +1280,53 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/staff(M), slot_l_hand) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) equip_special_id(M,get_all_accesses(), "Wizard", /obj/item/weapon/card/id) + if("soviet tourist") + M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/head/ushanka(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M), slot_in_backpack) + equip_special_id(M,list(access_maint_tunnels), "Soviet Tourist", /obj/item/weapon/card/id) + + if("soviet soldier") + M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/head/ushanka(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/syndicate(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/card/emag(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/c4(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/c4(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + equip_special_id(M,list(access_maint_tunnels), "Soviet Soldier", /obj/item/weapon/card/id) + if("soviet admiral") + M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) M.equip_to_slot_or_del(new /obj/item/clothing/head/hgpiratecap(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/syndicate(M), slot_l_ear) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) - equip_special_id(M,get_all_accesses() + get_all_centcom_access(), "Admiral", /obj/item/weapon/card/id, "commander") + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack) + equip_special_id(M,get_all_accesses() + get_all_centcom_access(), "Soviet Admiral", /obj/item/weapon/card/id, "commander") //W.icon_state = "commander" if("chrono legionnaire") @@ -1201,19 +1371,25 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Yes","No") != "Yes") return - for(var/obj/machinery/power/emitter/E in world) + for(var/obj/machinery/power/emitter/E in machines) if(E.anchored) E.active = 1 - for(var/obj/machinery/field/generator/F in world) - if(F.anchored) - F.Varedit_start = 1 + for(var/obj/machinery/field/generator/F in machines) + if(F.active == 0) + F.active = 1 + F.state = 2 + F.power = 250 + F.anchored = 1 + F.warming_up = 3 + F.start_fields() + F.update_icon() + spawn(30) - for(var/obj/machinery/the_singularitygen/G in world) + for(var/obj/machinery/the_singularitygen/G in machines) if(G.anchored) var/obj/singularity/S = new /obj/singularity(get_turf(G), 50) - spawn(0) - qdel(G) +// qdel(G) S.energy = 1750 S.current_size = 7 S.icon = 'icons/effects/224x224.dmi' @@ -1227,7 +1403,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that //S.dissipate_track = 0 //S.dissipate_strength = 10 - for(var/obj/machinery/power/rad_collector/Rad in world) + for(var/obj/machinery/power/rad_collector/Rad in machines) if(Rad.anchored) if(!Rad.P) var/obj/item/weapon/tank/plasma/Plasma = new/obj/item/weapon/tank/plasma(Rad) @@ -1239,7 +1415,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(!Rad.active) Rad.toggle_power() - for(var/obj/machinery/power/smes/SMES in world) + for(var/obj/machinery/power/smes/SMES in machines) if(SMES.anchored) SMES.input_attempt = 1 diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 3537dd3d6df..92af790dc4b 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -21,7 +21,7 @@ var/global/list/frozen_mob_list = list() ///mob freeze procs -/mob/living/var/frozen = 0 //used for preventing attacks on admin-frozen mobs +/mob/living/var/frozen = null //used for preventing attacks on admin-frozen mobs /mob/living/var/admin_prev_sleeping = 0 //used for keeping track of previous sleeping value with admin freeze /mob/living/proc/admin_Freeze(var/client/admin) @@ -34,7 +34,7 @@ var/global/list/frozen_mob_list = list() src.overlays += AO anchored = 1 - frozen = 1 + frozen = AO admin_prev_sleeping = sleeping sleeping += 20000 if(!(src in frozen_mob_list)) @@ -46,15 +46,16 @@ var/global/list/frozen_mob_list = list() message_admins("\blue [key_name_admin(admin)] unfroze [key_name_admin(src)]") log_admin("[key_name(admin)] unfroze [key_name(src)]") - update_icons() - anchored = 0 - frozen = 0 + overlays -= frozen + frozen = null sleeping = admin_prev_sleeping admin_prev_sleeping = null if(src in frozen_mob_list) frozen_mob_list -= src + update_icons() + /mob/living/carbon/slime/admin_Freeze(admin) ..(admin) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 6578898a0bd..d58e51971dd 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -139,7 +139,9 @@ var/list/admin_verbs_show_debug_verbs = list( /client/proc/print_jobban_old_filter, /client/proc/forceEvent, /client/proc/nanomapgen_DumpImage, - /client/proc/reload_nanoui_resources + /client/proc/reload_nanoui_resources, + /client/proc/admin_redo_space_transitions, + /client/proc/make_turf_space_map ) /client/proc/enable_debug_verbs() diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 5506b3b9076..8da22a71b62 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -146,40 +146,16 @@ client/proc/one_click_antag() return 0 /datum/admins/proc/makeWizard() - var/list/mob/candidates = list() - var/mob/theghost = null - var/time_passed = world.time - for(var/mob/G in respawnable_list) - if(istype(G) && G.client && (ROLE_WIZARD in G.client.prefs.be_special)) - if(!jobban_isbanned(G, "wizard") && !jobban_isbanned(G, "Syndicate")) - if(player_old_enough_antag(G.client,ROLE_WIZARD)) - spawn(0) - switch(G.timed_alert("Do you wish to be considered for the position of Space Wizard Foundation 'diplomat'?","Please answer in 30 seconds!","No",300,"Yes","No"))//alert(G, "Do you wish to be considered for the position of Space Wizard Foundation 'diplomat'?","Please answer in 30 seconds!","Yes","No")) - if("Yes") - if((world.time-time_passed)>300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) + var/list/candidates = pollCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard") if(candidates.len) - candidates = shuffle(candidates) - for(var/mob/dead/observer/i in candidates) - if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard + var/mob/dead/observer/selected = pick(candidates) + candidates -= selected - theghost = i - break - - if(theghost) - var/mob/living/carbon/human/new_character=makeBody(theghost) + var/mob/living/carbon/human/new_character = makeBody(selected) new_character.mind.make_Wizard() return 1 - return 0 diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 47c7da15724..660a1c8f199 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -81,6 +81,7 @@ var/list/sounds_cache = list() for(var/O in global_intercoms) var/obj/item/device/radio/intercom/I = O + // TODO: Tie into space manager if(I.z != ZLEVEL_STATION && !ignore_z) continue if(!I.on && !ignore_power) diff --git a/code/modules/admin/verbs/serialization.dm b/code/modules/admin/verbs/serialization.dm new file mode 100644 index 00000000000..41ba5d11aa1 --- /dev/null +++ b/code/modules/admin/verbs/serialization.dm @@ -0,0 +1,26 @@ +/client/proc/admin_serialize() + set name = "Serialize Marked Datum" + set desc = "Turns your marked object into a JSON string you can later use to re-create the object" + set category = "Debug" + + if(!check_rights(R_ADMIN)) + return + + if(!istype(holder.marked_datum, /atom/movable)) + to_chat(src, "The marked datum is not an atom/movable!") + return + + var/atom/movable/AM = holder.marked_datum + to_chat(src, json_encode(AM.serialize())) + +/client/proc/admin_deserialize() + set name = "Deserialize JSON datum" + set desc = "Creates an object from a JSON string" + set category = "Debug" + + if(!check_rights(R_ADMIN|R_DEBUG)) + return + + var/json_text = input("Enter the JSON code:","Text") as message|null + if(json_text) + json_to_object(json_text, get_turf(usr)) \ No newline at end of file diff --git a/code/modules/admin/verbs/space_transitions.dm b/code/modules/admin/verbs/space_transitions.dm new file mode 100644 index 00000000000..eda17996c65 --- /dev/null +++ b/code/modules/admin/verbs/space_transitions.dm @@ -0,0 +1,41 @@ +/client/proc/admin_redo_space_transitions() + set name = "Remake Space Transitions" + set desc = "Re-assigns all space transitions" + set category = "Debug" + + if(!check_rights(R_ADMIN|R_DEBUG)) + return + + var/choice = alert("Do you want to rebuild space transitions?",,"Yes", "No") + + if(choice == "No") + return + + + message_admins("[key_name_admin(usr)] re-assigned all space transitions") + space_manager.do_transition_setup() + log_admin("[key_name(usr)] re-assigned all space transitions") + + feedback_add_details("admin_verb","SPCRST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + + +/client/proc/make_turf_space_map() + set name = "Make Space Map" + set desc = "Create a map of the space levels as turfs at your feet" + set category = "Debug" + + if(!check_rights(R_ADMIN|R_DEBUG)) + return + + var/choice = alert("Are you sure you want to make a space map out of turfs?",,"Yes","No") + + if(choice == "No") + return + + message_admins("[key_name_admin(usr)] made a space map") + + + space_manager.map_as_turfs(get_turf(usr)) + log_admin("[key_name(usr)] made a space map") diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index fcfd8d2e600..9cb75d4a22b 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -96,7 +96,7 @@ var/global/dmm_suite/preloader/_preloader = new if(cropMap) continue else - zlevels.increase_max_zlevel_to(zcrd) //create a new z_level if needed + space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart) bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd) @@ -228,10 +228,12 @@ var/global/dmm_suite/preloader/_preloader = new var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp} var/variables_start = findtext(full_def, "{") - var/atom_def = text2path(trim_text(copytext(full_def, 1, variables_start))) //path definition, e.g /obj/foo/bar + var/atom_text = trim_text(copytext(full_def, 1, variables_start)) + var/atom_def = text2path(atom_text) //path definition, e.g /obj/foo/bar old_position = dpos + 1 if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers! + log_debug("Bad path: [atom_text]") continue members.Add(atom_def) @@ -378,8 +380,15 @@ var/global/dmm_suite/preloader/_preloader = new var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable //Check for string + // Make it read to the next delimiter, instead of the quote if(findtext(trim_right,quote,1,2)) - trim_right = copytext(trim_right,2,findtext(trim_right,quote,3,0)) + var/endquote = findtext(trim_right,quote,-1) + if(!endquote) + log_debug("Terminating quote not found!") + // Our map writer escapes quotes and curly brackets to avoid + // letting our simple parser choke on meanly-crafted names/etc + // - so we decode it here so it's back to good ol' legibility + trim_right = dmm_decode(copytext(trim_right,2,endquote)) //Check for number else if(isnum(text2num(trim_right))) @@ -430,14 +439,27 @@ var/global/dmm_suite/preloader/_preloader = new parent_type = /datum var/list/attributes var/target_path + var/json_ready = 0 /dmm_suite/preloader/proc/setup(list/the_attributes, path) if(the_attributes.len) + json_ready = 0 + if("map_json_data" in the_attributes) + json_ready = 1 use_preloader = TRUE attributes = the_attributes target_path = path /dmm_suite/preloader/proc/load(atom/what) + if(json_ready) + var/json_data = attributes["map_json_data"] + attributes -= "map_json_data" + json_data = dmm_decode(json_data) + try + what.deserialize(json_decode(json_data)) + catch(var/exception/e) + log_debug("Bad json data: '[json_data]'") + throw e for(var/attribute in attributes) var/value = attributes[attribute] if(islist(value)) diff --git a/code/modules/awaymissions/maploader/swapmaps.dm b/code/modules/awaymissions/maploader/swapmaps.dm index 7115cfcbf13..fab504b150d 100644 --- a/code/modules/awaymissions/maploader/swapmaps.dm +++ b/code/modules/awaymissions/maploader/swapmaps.dm @@ -326,7 +326,7 @@ swapmap x2+=x1-1 y2+=y1-1 z2+=z1-1 - zlevels.increase_max_zlevel_to(z2) // stretch z if necessary + space_manager.increase_max_zlevel_to(z2) // stretch z if necessary if(!ischunk) swapmaps_loaded[src]=null swapmaps_byname[id]=src @@ -373,7 +373,7 @@ swapmap mz=max(mz,M.z2) world.maxx=mx world.maxy=my - zlevels.cut_levels_downto(mz) + space_manager.cut_levels_downto(mz) // save and delete proc/Unload() diff --git a/code/modules/awaymissions/maploader/writer.dm b/code/modules/awaymissions/maploader/writer.dm index 208d0935a32..842a51fbce5 100644 --- a/code/modules/awaymissions/maploader/writer.dm +++ b/code/modules/awaymissions/maploader/writer.dm @@ -4,10 +4,10 @@ #define DMM_IGNORE_NPCS 8 #define DMM_IGNORE_PLAYERS 16 #define DMM_IGNORE_MOBS 24 -dmm_suite{ - var{ - quote = "\"" - list/letter_digits = list( +#define DMM_USE_JSON 32 +/dmm_suite + var/quote = "\"" + var/list/letter_digits = list( "a","b","c","d","e", "f","g","h","i","j", "k","l","m","n","o", @@ -21,154 +21,202 @@ dmm_suite{ "U","V","W","X","Y", "Z" ) - } - save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){ - //Check for illegal characters in file name... in a cheap way. - if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name))){ - CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.") - } - //Check for valid turfs. - if(!isturf(t1) || !isturf(t2)){ - CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.") - } - var/file_text = write_map(t1,t2,flags) - if(fexists("[map_name].dmm")){ - fdel("[map_name].dmm") - } - var/saved_map = file("[map_name].dmm") - saved_map << file_text - return saved_map - } - write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){ - //Check for valid turfs. - if(!isturf(t1) || !isturf(t2)){ - CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.") - } - var/turf/nw = locate(min(t1.x,t2.x),max(t1.y,t2.y),min(t1.z,t2.z)) - var/turf/se = locate(max(t1.x,t2.x),min(t1.y,t2.y),max(t1.z,t2.z)) - var/list/templates[0] - var/template_buffer = {""} - var/dmm_text = {""} - for(var/pos_z in nw.z to se.z){ - for(var/pos_y in nw.y to se.y){ - for(var/pos_x in nw.x to se.x){ - var/turf/test_turf = locate(pos_x,pos_y,pos_z) - var/test_template = make_template(test_turf, flags) - var/template_number = templates.Find(test_template) - if(!template_number){ - templates.Add(test_template) - template_number = templates.len - } - template_buffer += "[template_number]," - } - template_buffer += ";" - } - template_buffer += "." - } - var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1) - var/list/keys[templates.len] - for(var/key_pos in 1 to templates.len){ - keys[key_pos] = get_model_key(key_pos,key_length) - dmm_text += {""[keys[key_pos]]" = ([templates[key_pos]])\n"} - } - var/z_level = 0 - for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer,".",z_pos)+1){ - if(z_pos>=length(template_buffer)){break} - if(z_level){dmm_text+={"\n"}} - dmm_text += {"\n(1,1,[++z_level]) = {"\n"} - var/z_block = copytext(template_buffer,z_pos,findtext(template_buffer,".",z_pos)) - for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1){ - if(y_pos>=length(z_block)){break} - var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos)) - for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1){ - if(x_pos>=length(y_block)){break} - var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos)) - var/key_number = text2num(x_block) - var/temp_key = keys[key_number] - dmm_text += temp_key - sleep(-1) - } - dmm_text += {"\n"} - sleep(-1) - } - dmm_text += {"\"}"} - sleep(-1) - } - return dmm_text - } - proc{ - make_template(var/turf/model as turf, var/flags as num){ - var/template = "" - var/obj_template = "" - var/mob_template = "" - var/turf_template = "" - if(!(flags & DMM_IGNORE_TURFS)){ - turf_template = "[model.type][check_attributes(model)]," - } else{ turf_template = "[world.turf],"} - var/area_template = "" - if(!(flags & DMM_IGNORE_OBJS)){ - for(var/obj/O in model.contents){ - obj_template += "[O.type][check_attributes(O)]," - } - } - for(var/mob/M in model.contents){ - if(M.client){ - if(!(flags & DMM_IGNORE_PLAYERS)){ - mob_template += "[M.type][check_attributes(M)]," - } - } - else{ - if(!(flags & DMM_IGNORE_NPCS)){ - mob_template += "[M.type][check_attributes(M)]," - } - } - } - if(!(flags & DMM_IGNORE_AREAS)){ - var/area/m_area = model.loc - area_template = "[m_area.type][check_attributes(m_area)]" - } else{ area_template = "[world.area]"} - template = "[obj_template][mob_template][turf_template][area_template]" - return template - } - check_attributes(var/atom/A){ - var/attributes_text = {"{"} - for(var/V in A.vars){ - sleep(-1) - if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))){continue} - if(istext(A.vars[V])){ - attributes_text += {"[V] = "[A.vars[V]]""} - } - else if(isnum(A.vars[V])||ispath(A.vars[V])){ - attributes_text += {"[V] = [A.vars[V]]"} - } - else if(isicon(A.vars[V])||isfile(A.vars[V])){ - attributes_text += {"[V] = '[A.vars[V]]'"} - } - else{ - continue - } - if(attributes_text != {"{"}){ - attributes_text+={"; "} - } - } - if(attributes_text=={"{"}){ - return - } - if(copytext(attributes_text, length(attributes_text)-1, 0) == {"; "}){ - attributes_text = copytext(attributes_text, 1, length(attributes_text)-1) - } - attributes_text += {"}"} - return attributes_text - } - get_model_key(var/which as num, var/key_length as num){ - var/key = "" - var/working_digit = which-1 - for(var/digit_pos in key_length to 1 step -1){ - var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1))) - working_digit-=place_value*(letter_digits.len**(digit_pos-1)) - key = "[key][letter_digits[place_value+1]]" - } - return key - } - } - } \ No newline at end of file + +/dmm_suite/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num) + //Check for illegal characters in file name... in a cheap way. + if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name))) + CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.") + //Check for valid turfs. + if(!isturf(t1) || !isturf(t2)) + CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.") + + var/map_prefix = "_maps/quicksave/" + var/map_path = "[map_prefix][map_name].dmm" + if(fexists(map_path)) + fdel(map_path) + var/saved_map = file(map_path) + var/map_text = write_map(t1,t2,flags,saved_map) + saved_map << map_text + return saved_map + +/dmm_suite/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num) + //Check for valid turfs. + if(!isturf(t1) || !isturf(t2)) + CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.") + + var/turf/ne = locate(max(t1.x,t2.x),max(t1.y,t2.y),max(t1.z,t2.z)) // Outer corner + var/turf/sw = locate(min(t1.x,t2.x),min(t1.y,t2.y),min(t1.z,t2.z)) // Inner corner + var/list/templates[0] + var/list/template_buffer = list() + var/template_buffer_text + var/dmm_text = "" + + var/total_timer = start_watch() + var/timer = start_watch() + log_debug("Reading turfs...") + // Read the contents of all the turfs we were given + for(var/pos_z in sw.z to ne.z) + for(var/pos_y in ne.y to sw.y step -1) // We're reversing this because the map format is silly + for(var/pos_x in sw.x to ne.x) + var/turf/test_turf = locate(pos_x,pos_y,pos_z) + var/test_template = make_template(test_turf, flags) + var/template_number = templates.Find(test_template) + if(!template_number) + templates.Add(test_template) + template_number = templates.len + template_buffer += "[template_number]," + CHECK_TICK + + template_buffer += ";" + + template_buffer += "." + template_buffer_text = jointext(template_buffer,"") + log_debug("Reading turfs took [stop_watch(timer)]s.") + + if(templates.len == 0) + CRASH("No templates found!") + var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1) + var/list/keys[templates.len] + // Write the list of key/model pairs to the file + timer = start_watch() + log_debug("Writing out key/model pairs to file header...") + var/list/key_models = list() + for(var/key_pos in 1 to templates.len) + keys[key_pos] = get_model_key(key_pos,key_length) + key_models += "\"[keys[key_pos]]\" = ([templates[key_pos]])\n" + CHECK_TICK + dmm_text += jointext(key_models,"") + log_debug("Writing key/model pairs complete, took [stop_watch(timer)]s.") + + var/z_level = 0 + // Loop over all z in our zone + timer = start_watch() + log_debug("Writing out key map...") + var/list/key_map = list() + for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer_text,".",z_pos)+1) + if(z_pos>=length(template_buffer_text)) break + if(z_level) key_map += "\n" + key_map += "\n(1,1,[++z_level]) = {\"\n" + var/z_block = copytext(template_buffer_text,z_pos,findtext(template_buffer_text,".",z_pos)) + for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1) + if(y_pos>=length(z_block)) break + var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos)) + // A row of keys + for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1) + if(x_pos>=length(y_block)) break + var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos)) + var/key_number = text2num(x_block) + var/temp_key = keys[key_number] + key_map += temp_key + CHECK_TICK + key_map += "\n" + key_map += "\"}" + dmm_text += jointext(key_map,"") + log_debug("Writing key map complete, took [stop_watch(timer)]s.") + log_debug("TOTAL TIME: [stop_watch(total_timer)]s.") + return dmm_text + +/dmm_suite/proc/make_template(var/turf/model as turf, var/flags as num) + var/use_json = 0 + if(flags & DMM_USE_JSON) + use_json = 1 + var/template = "" + var/turf_template = "" + var/list/obj_template = list() + var/list/mob_template = list() + var/area_template = "" + + + + // Turf + if(!(flags & DMM_IGNORE_TURFS)) + turf_template = "[model.type][check_attributes(model,use_json=use_json)]," + else turf_template = "[world.turf]," + + // Objects loop + if(!(flags & DMM_IGNORE_OBJS)) + for(var/obj/O in model.contents) + if(O.dont_save || !isnull(O.gcDestroyed)) + continue + obj_template += "[O.type][check_attributes(O,use_json=use_json)]," + + // Mobs Loop + for(var/mob/M in model.contents) + if(M.dont_save || !isnull(M.gcDestroyed)) + continue + if(M.client) + if(!(flags & DMM_IGNORE_PLAYERS)) + mob_template += "[M.type][check_attributes(M,use_json=use_json)]," + else + if(!(flags & DMM_IGNORE_NPCS)) + mob_template += "[M.type][check_attributes(M,use_json=use_json)]," + + // Area + if(!(flags & DMM_IGNORE_AREAS)) + var/area/m_area = model.loc + area_template = "[m_area.type][check_attributes(m_area,use_json=use_json)]" + else area_template = "[world.area]" + + template = "[jointext(obj_template,"")][jointext(mob_template,"")][turf_template][area_template]" + return template + +/dmm_suite/proc/check_attributes(var/atom/A,use_json=0) + var/attributes_text = "{" + var/list/attributes = list() + if(!use_json) + for(var/V in A.vars) + CHECK_TICK + if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))) continue + + attributes += var_to_dmm(A.vars[V], V) + else + var/list/yeah = A.serialize() + // We'll want to write out vars that are important to the editor + // So that the map is legible as before + for(var/thing in A.map_important_vars()) + // Save vars that are important for the map editor, so that + // json-encoded maps are legible for standard editors + if(A.vars[thing] != initial(A.vars[thing])) + yeah -= thing + attributes += var_to_dmm(A.vars[thing],thing) + + // Remove useless info + yeah -= "type" + if(yeah.len) + var/json_stuff = json_encode(yeah) + attributes += var_to_dmm(json_stuff, "map_json_data") + if(attributes.len == 0) + return + + // Trim a trailing semicolon - `var_to_dmm` always appends a semicolon, + // so the last one will be trailing. + if(copytext(attributes_text, length(attributes_text)-1, 0) == "; ") + attributes_text = copytext(attributes_text, 1, length(attributes_text)-1) + attributes_text = "{[jointext(attributes,"; ")]}" + return attributes_text + + +/dmm_suite/proc/get_model_key(var/which as num, var/key_length as num) + var/list/key = list() + var/working_digit = which-1 + for(var/digit_pos in key_length to 1 step -1) + var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1))) + working_digit-=place_value*(letter_digits.len**(digit_pos-1)) + key += letter_digits[place_value+1] + return jointext(key,"") + + +/dmm_suite/proc/var_to_dmm(attr, name) + if(istext(attr)) + // dmm_encode will strip out characters that would be capable of disrupting + // parsing - namely, quotes and curly braces + return "[name] = \"[dmm_encode(attr)]\"" + else if(isnum(attr)||ispath(attr)) + return "[name] = [attr]" + else if(isicon(attr)||isfile(attr)) + if(length("[attr]") == 0) + // The DM map reader is unable to read files that have a '' file/icon entry + return + return "[name] = '[attr]'" + else + return "" diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm index b7670737193..d1e9a9555be 100644 --- a/code/modules/awaymissions/mission_code/spacehotel.dm +++ b/code/modules/awaymissions/mission_code/spacehotel.dm @@ -92,7 +92,6 @@ icon = 'icons/obj/doors/Doorsand.dmi' icon_state = "door_closed" autoclose = 1 - atom_say_verb = "beeps" var/doorOpen = 'sound/machines/airlock.ogg' var/doorClose = 'sound/machines/airlock.ogg' var/doorDeni = 'sound/machines/DeniedBeep.ogg' diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index 7fff68cf031..da6515a591d 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -59,15 +59,13 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away var/map = pick(potentialRandomZlevels) var/file = file(map) if(isfile(file)) - var/zlev = zlevels.add_new_zlevel() - zlevels.add_dirt(zlev) + var/zlev = space_manager.add_new_zlevel(AWAY_MISSION, linkage = UNAFFECTED) + space_manager.add_dirt(zlev) maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) - zlevels.remove_dirt(zlev) + space_manager.remove_dirt(zlev) log_to_dd(" Away mission loaded: [map]") - //map_transition_config.Add(AWAY_MISSION_LIST) - for(var/obj/effect/landmark/L in landmarks_list) if(L.name != "awaystart") continue @@ -91,11 +89,11 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away var/file = file(map) if(isfile(file)) log_startup_progress("Loading away mission: [map]") - var/zlev = zlevels.add_new_zlevel() - zlevels.add_dirt(zlev) + var/zlev = space_manager.add_new_zlevel() + space_manager.add_dirt(zlev) maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) - zlevels.remove_dirt(zlev) + space_manager.remove_dirt(zlev) log_to_dd(" Away mission loaded: [map]") //map_transition_config.Add(AWAY_MISSION_LIST) @@ -151,8 +149,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away var/initialbudget = budget var/watch = start_watch() - log_startup_progress("Loading ruins...") - while(budget > 0 && overall_sanity > 0) // Pick a ruin var/datum/map_template/ruin/ruin = ruins[pick(ruins)] @@ -187,7 +183,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away ruins -= ruin.name break - to_chat(world, " Loaded ruins. Or not.") //So the players don't know if we loaded ruins, but we do have a message if(initialbudget == budget) //Kill me log_to_dd(" No ruins loaded.") diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 0d56f0d1122..7a87264d815 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -57,7 +57,6 @@ if( findtext(href,"[user] snips the fingertips off [src].","You snip the fingertips off [src].") + clipped = 1 + name = "mangled [name]" + desc = "[desc] They have had the fingertips cut off of them." + update_icon() + else + to_chat(user, "[src] have already been clipped!") + return + else + ..() + /obj/item/clothing/under/proc/set_sensors(mob/user as mob) var/mob/M = user if(istype(M, /mob/dead/)) return @@ -510,6 +523,7 @@ BLIND // can't see anything flash_protect = 2 strip_delay = 50 put_on_delay = 50 + burn_state = FIRE_PROOF /obj/item/clothing/suit/space name = "Space suit" @@ -531,6 +545,7 @@ BLIND // can't see anything max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT strip_delay = 80 put_on_delay = 80 + burn_state = FIRE_PROOF species_restricted = list("exclude","Diona","Vox","Wryn") //Under clothing diff --git a/code/modules/clothing/ears/ears.dm b/code/modules/clothing/ears/ears.dm new file mode 100644 index 00000000000..672df573858 --- /dev/null +++ b/code/modules/clothing/ears/ears.dm @@ -0,0 +1,28 @@ +/obj/item/clothing/ears/earmuffs + name = "earmuffs" + desc = "Protects your hearing from loud noises, and quiet ones as well." + icon_state = "earmuffs" + item_state = "earmuffs" + flags = EARBANGPROTECT + strip_delay = 15 + put_on_delay = 25 + burn_state = FLAMMABLE + +/obj/item/clothing/ears/headphones + name = "headphones" + desc = "Unce unce unce unce." + var/on = 0 + icon_state = "headphones0" + item_state = "earmuffs" + actions_types = list(/datum/action/item_action/toggle_headphones) + burn_state = FLAMMABLE + +/obj/item/clothing/ears/headphones/attack_self(mob/user) + on = !on + icon_state = "headphones[on]" + + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + + user.update_inv_ears() \ No newline at end of file diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 6a51086c7b3..5719f006dd4 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -234,6 +234,10 @@ "Drask" = 'icons/mob/species/drask/eyes.dmi' ) +/obj/item/clothing/glasses/sunglasses/fake + desc = "Cheap, plastic sunglasses. They don't even have UV protection." + name = "cheap sunglasses" + flash_protect = 0 /obj/item/clothing/glasses/sunglasses/noir name = "noir sunglasses" diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 76bfbdfd394..11503b40278 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -6,6 +6,7 @@ siemens_coefficient = 0 permeability_coefficient = 0.05 item_color="yellow" + burn_state = FIRE_PROOF /obj/item/clothing/gloves/color/yellow/power description_antag = "These are a pair of power gloves, and can be used to fire bolts of electricity while standing over powered power cables." @@ -45,6 +46,7 @@ siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() permeability_coefficient = 0.05 item_color="yellow" + burn_state = FIRE_PROOF New() siemens_coefficient = pick(0,0.5,0.5,0.5,0.5,0.75,1.5) @@ -59,6 +61,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + burn_state = FIRE_PROOF var/can_be_cut = 1 @@ -80,6 +83,7 @@ if(pickpocket) F.pickpocket = 1 qdel(src) + return ..() /obj/item/clothing/gloves/color/orange @@ -101,6 +105,7 @@ desc = "These gloves will protect the wearer from electric shock." siemens_coefficient = 0 permeability_coefficient = 0.05 + burn_state = FIRE_PROOF /obj/item/clothing/gloves/color/rainbow name = "rainbow gloves" @@ -171,6 +176,7 @@ permeability_coefficient = 0.01 item_color="white" transfer_prints = TRUE + burn_state = FIRE_PROOF /obj/item/clothing/gloves/color/latex/nitrile name = "nitrile gloves" diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index feae32b9085..db9de4df740 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -9,6 +9,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT strip_delay = 40 put_on_delay = 20 + clipped = 1 /obj/item/clothing/gloves/cyborg desc = "beep boop borp" @@ -28,6 +29,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + burn_state = FIRE_PROOF /obj/item/clothing/gloves/botanic_leather desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin." @@ -39,6 +41,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + burn_state = FIRE_PROOF /obj/item/clothing/gloves/batmangloves desc = "Used for handling all things bat related." diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index 977a3969a93..bbaf5b34e8b 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -58,6 +58,7 @@ desc = "A Collectable Welding Helmet. Now with 80% less lead! Not for actual welding. Any welding done while wearing this Helmet is done so at the owner's own risk!" icon_state = "welding" item_state = "welding" + burn_state = FIRE_PROOF species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/helmet.dmi', @@ -117,12 +118,14 @@ desc = "Go Red! I mean Green! I mean Red! No Green!" icon_state = "thunderdome" item_state = "thunderdome" + burn_state = FIRE_PROOF /obj/item/clothing/head/collectable/swat name = "collectable SWAT helmet" desc = "Now you can be in the Deathsquad too!" icon_state = "swat" item_state = "swat" + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/helmet.dmi' diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 5cc5af80abb..c73a6f21306 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -10,6 +10,7 @@ armor = list(melee = 15, bullet = 5, laser = 20, energy = 10, bomb = 20, bio = 10, rad = 20) flags_inv = 0 actions_types = list(/datum/action/item_action/toggle_helmet_light) + burn_state = FIRE_PROOF /obj/item/clothing/head/hardhat/attack_self(mob/user) on = !on diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index b7b0cc71b81..f31a6434001 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -11,6 +11,7 @@ heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 60 + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/helmet.dmi', diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 6e53e8a9b04..c6879cb2945 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -342,6 +342,7 @@ throw_range = 5 w_class = 2 attack_verb = list("warned", "cautioned", "smashed") + burn_state = FIRE_PROOF /obj/item/clothing/head/griffin name = "griffon head" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 703f36cf1fd..eb04efcc380 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -23,6 +23,7 @@ armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) actions_types = list(/datum/action/item_action/toggle) + burn_state = FIRE_PROOF species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/head.dmi', diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 5b3ab335cbe..295ec84c4af 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -8,6 +8,7 @@ gas_transfer_coefficient = 0.10 permeability_coefficient = 0.50 actions_types = list(/datum/action/item_action/adjust) + burn_state = FIRE_PROOF species_fit = list("Vox", "Vox Armalis", "Unathi", "Tajaran", "Vulpkanin") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/mask.dmi', diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 72b4b6febb7..0df0f7550fc 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -8,6 +8,7 @@ item_state = "gas_alt" gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 + burn_state = FIRE_PROOF species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/mask.dmi', @@ -95,6 +96,7 @@ icon_state = "clown" item_state = "clown_hat" flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | AIRTIGHT | BLOCKHAIR + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/clown_hat/attack_self(mob/user) @@ -130,24 +132,28 @@ desc = "A feminine clown mask for the dabbling crossdressers or female entertainers." icon_state = "sexyclown" item_state = "sexyclown" + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/mime name = "mime mask" desc = "The traditional mime's mask. It has an eerie facial posture." icon_state = "mime" item_state = "mime" + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/monkeymask name = "monkey mask" desc = "A mask used when acting as a monkey." icon_state = "monkeymask" item_state = "monkeymask" + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/sexymime name = "sexy mime mask" desc = "A traditional female mime's mask." icon_state = "sexymime" item_state = "sexymime" + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/death_commando name = "Death Commando Mask" @@ -158,12 +164,14 @@ name = "cyborg visor" desc = "Beep boop" icon_state = "death" + burn_state = FLAMMABLE /obj/item/clothing/mask/gas/owl_mask name = "owl mask" desc = "Twoooo!" icon_state = "owl" flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | AIRTIGHT | NODROP + burn_state = FLAMMABLE actions_types = list(/datum/action/item_action/hoot) /obj/item/clothing/mask/gas/owl_mask/attack_self() diff --git a/code/modules/clothing/masks/voice.dm b/code/modules/clothing/masks/voice.dm index 190804d1a92..8655c2b7541 100644 --- a/code/modules/clothing/masks/voice.dm +++ b/code/modules/clothing/masks/voice.dm @@ -9,6 +9,7 @@ // desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics." var/obj/item/voice_changer/changer origin_tech = "syndicate=4" + burn_state = FIRE_PROOF /obj/item/clothing/mask/gas/voice/verb/Toggle_Voice_Changer() set category = "Object" diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 2c6bdeddf87..b036946e4ae 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -8,6 +8,7 @@ actions_types = list(/datum/action/item_action/toggle) strip_delay = 70 put_on_delay = 70 + burn_state = FIRE_PROOF /obj/item/clothing/shoes/magboots/attack_self(mob/user) if(magpulse) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 2330f439547..f9aef32e067 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -6,6 +6,7 @@ permeability_coefficient = 0.05 flags = NOSLIP origin_tech = "syndicate=3" + burn_state = FIRE_PROOF var/list/clothing_choices = list() silence_steps = 1 @@ -22,6 +23,7 @@ item_state = "jackboots" armor = list(melee = 25, bullet = 25, laser = 25, energy = 25, bomb = 50, bio = 10, rad = 0) strip_delay = 70 + burn_state = FIRE_PROOF /obj/item/clothing/shoes/combat/swat //overpowered boots for death squads name = "\improper SWAT shoes" @@ -51,6 +53,7 @@ slowdown = SHOES_SLOWDOWN+1 strip_delay = 50 put_on_delay = 50 + burn_state = FIRE_PROOF /obj/item/clothing/shoes/galoshes/dry name = "absorbent galoshes" @@ -82,6 +85,7 @@ item_color = "hosred" strip_delay = 50 put_on_delay = 50 + burn_state = FIRE_PROOF var/footstep = 1 silence_steps = 1 shoe_sound = "jackboot" diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 40e64add719..c50e9b1c6d3 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -115,6 +115,7 @@ to_chat(H, "You cannot teleport into solid walls.") return 0*///Who the fuck cares? Ninjas in walls are cool. + // TODO: Tie into space manager if(T.z in config.admin_levels) to_chat(H, "You cannot use your teleporter on this Z-level.") return 0 diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 8b5ea0d9af5..d46d7f83d1d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -7,6 +7,7 @@ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT strip_delay = 60 put_on_delay = 40 + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -148,6 +149,7 @@ cold_protection = UPPER_TORSO|LOWER_TORSO|HANDS heat_protection = UPPER_TORSO|LOWER_TORSO|HANDS strip_delay = 70 + burn_state = FLAMMABLE /obj/item/clothing/suit/armor/vest/warden/alt name = "warden's jacket" @@ -235,7 +237,7 @@ blood_overlay_type = "armor" flags_size = ONESIZEFITSALL allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/device/flashlight,/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) - + burn_state = FLAMMABLE //Reactive armor /obj/item/clothing/suit/armor/reactive diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 06fbf32b056..4286064262f 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -7,6 +7,7 @@ flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR | THICKMATERIAL armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES + burn_state = FIRE_PROOF /obj/item/clothing/suit/bio_suit name = "bio suit" @@ -25,6 +26,7 @@ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL strip_delay = 70 put_on_delay = 70 + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index a8fd6ea4c49..5124e1d1adf 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -189,6 +189,7 @@ item_state = "hazard" blood_overlay_type = "armor" allowed = list (/obj/item/device/flashlight, /obj/item/device/t_scanner, /obj/item/weapon/tank/emergency_oxygen) + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 676800f8f48..ef89720e0e3 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -17,6 +17,7 @@ blood_overlay_type = "armor" body_parts_covered = UPPER_TORSO|LOWER_TORSO allowed = list (/obj/item/weapon/gun/energy/laser/bluetag) + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -30,6 +31,7 @@ blood_overlay_type = "armor" body_parts_covered = UPPER_TORSO|LOWER_TORSO allowed = list (/obj/item/weapon/gun/energy/laser/redtag) + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -136,6 +138,7 @@ w_class = 3 allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + burn_state = FIRE_PROOF /obj/item/clothing/suit/hastur @@ -407,7 +410,7 @@ name = "black hoodie" desc = "It's a hoodie. It has a hood. Most hoodies do." icon_state = "black_hoodie" - item_state = "labcoat" + item_state = "blueshieldcoat" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS hoodtype = /obj/item/clothing/head/hood species_fit = list("Vox") @@ -515,6 +518,7 @@ desc = "A long, thick black leather coat." icon_state = "leathercoat" item_state = "leathercoat" + burn_state = FIRE_PROOF /obj/item/clothing/suit/browncoat name = "brown leather coat" @@ -748,6 +752,7 @@ ignore_suitadjust = 1 actions_types = list() adjust_flavour = null + burn_state = FIRE_PROOF /obj/item/clothing/suit/officercoat name = "Clown Officer's Coat" diff --git a/code/modules/clothing/suits/storage.dm b/code/modules/clothing/suits/storage.dm index 360c9b2915f..82a468d2a63 100644 --- a/code/modules/clothing/suits/storage.dm +++ b/code/modules/clothing/suits/storage.dm @@ -23,7 +23,7 @@ /obj/item/clothing/suit/storage/attackby(obj/item/W as obj, mob/user as mob, params) ..() - pockets.attackby(W, user, params) + return pockets.attackby(W, user, params) /obj/item/clothing/suit/storage/emp_act(severity) pockets.emp_act(severity) @@ -50,3 +50,12 @@ if(istype(G.gift, /obj/item/weapon/storage)) L += G.gift:return_inv() return L + +/obj/item/clothing/suit/storage/serialize() + var/list/data = ..() + data["pockets"] = pockets.serialize() + return data + +/obj/item/clothing/suit/storage/deserialize(list/data) + qdel(pockets) + pockets = list_to_object(data["pockets"], src) diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 2178821e3fa..44a2f5b1c49 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -28,6 +28,7 @@ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT strip_delay = 60 put_on_delay = 60 + burn_state = FIRE_PROOF /obj/item/clothing/suit/fire/firefighter icon_state = "firesuit" @@ -72,6 +73,7 @@ max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 70 put_on_delay = 70 + burn_state = FIRE_PROOF /obj/item/clothing/suit/bomb_suit name = "bomb suit" @@ -92,6 +94,7 @@ min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT strip_delay = 70 put_on_delay = 70 + burn_state = FIRE_PROOF species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -119,6 +122,7 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 60, rad = 100) strip_delay = 60 put_on_delay = 60 + burn_state = FIRE_PROOF /obj/item/clothing/suit/radiation name = "Radiation suit" @@ -135,4 +139,5 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 60, rad = 100) flags_inv = HIDEJUMPSUIT|HIDETAIL strip_delay = 60 - put_on_delay = 60 \ No newline at end of file + put_on_delay = 60 + burn_state = FIRE_PROOF \ No newline at end of file diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index c36a3f3ecea..b8ee1c3c896 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -6,6 +6,7 @@ permeability_coefficient = 0.01 armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 20, rad = 20) unacidable = 1 + burn_state = FIRE_PROOF //Not given any special protective value since the magic robes are full-body protection --NEO strip_delay = 50 put_on_delay = 50 @@ -65,6 +66,7 @@ unacidable = 1 strip_delay = 50 put_on_delay = 50 + burn_state = FIRE_PROOF /obj/item/clothing/suit/wizrobe/red name = "red wizard robe" @@ -117,6 +119,7 @@ permeability_coefficient = 1 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) unacidable = 0 + burn_state = FLAMMABLE /obj/item/clothing/head/wizard/marisa/fake name = "Witch Hat" @@ -126,6 +129,7 @@ permeability_coefficient = 1 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) unacidable = 0 + burn_state = FLAMMABLE /obj/item/clothing/suit/wizrobe/marisa/fake name = "Witch Robe" @@ -135,4 +139,5 @@ gas_transfer_coefficient = 1 permeability_coefficient = 1 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) - unacidable = 0 \ No newline at end of file + unacidable = 0 + burn_state = FLAMMABLE \ No newline at end of file diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index e417c899f7f..9482ee7d080 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -30,6 +30,9 @@ var/mob/M = has_suit.loc A.Grant(M) + for(var/armor_type in armor) + has_suit.armor[armor_type] += armor[armor_type] + if(user) to_chat(user, "You attach [src] to [has_suit].") src.add_fingerprint(user) @@ -46,6 +49,9 @@ var/mob/M = has_suit.loc A.Remove(M) + for(var/armor_type in armor) + has_suit.armor[armor_type] -= armor[armor_type] + has_suit = null usr.put_in_hands(src) src.add_fingerprint(user) @@ -166,6 +172,7 @@ icon_state = "bronze" item_color = "bronze" materials = list(MAT_METAL=1000) + burn_state = FIRE_PROOF /obj/item/clothing/accessory/medal/conduct name = "distinguished conduct medal" diff --git a/code/modules/clothing/under/chameleon.dm b/code/modules/clothing/under/chameleon.dm index 8f5a540f3c3..8d7a92e3e8a 100644 --- a/code/modules/clothing/under/chameleon.dm +++ b/code/modules/clothing/under/chameleon.dm @@ -7,6 +7,7 @@ desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist." origin_tech = "syndicate=3" var/list/clothing_choices = list() + burn_state = FIRE_PROOF armor = list(melee = 10, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0) New() diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 886d48932aa..7b6b85326c3 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -17,6 +17,7 @@ item_state = "bl_suit" item_color = "black" flags_size = ONESIZEFITSALL + burn_state = FIRE_PROOF /obj/item/clothing/under/color/blackf name = "feminine black jumpsuit" diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 9b604da7277..2e01d170f3d 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -7,6 +7,7 @@ item_color = "chief" armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 10) flags_size = ONESIZEFITSALL + burn_state = FIRE_PROOF /obj/item/clothing/under/rank/chief_engineer/skirt desc = "It's a high visibility jumpskirt given to those engineers insane enough to achieve the rank of \"Chief engineer\". It has minor radiation shielding." @@ -23,6 +24,7 @@ item_state = "atmos_suit" item_color = "atmos" flags_size = ONESIZEFITSALL + burn_state = FIRE_PROOF /obj/item/clothing/under/rank/atmospheric_technician/skirt desc = "It's a jumpskirt worn by atmospheric technicians." @@ -40,6 +42,7 @@ item_color = "engine" armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 10) flags_size = ONESIZEFITSALL + burn_state = FIRE_PROOF /obj/item/clothing/under/rank/engineer/skirt diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 71eb07c89eb..31d36cdcb19 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -180,4 +180,12 @@ item_color = "brig_phys" permeability_coefficient = 0.50 armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0) - flags_size = ONESIZEFITSALL \ No newline at end of file + flags_size = ONESIZEFITSALL + +//Pod Pilot +/obj/item/clothing/under/rank/security/pod_pilot + desc = "Suit for your regular pod pilot." + name = "pod pilot's jumpsuit" + icon_state = "pod_pilot" + item_state = "pod_pilot" + item_color = "pod_pilot" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index d912a2e289d..c37d6340609 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -146,6 +146,7 @@ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT heat_protection = UPPER_TORSO | LOWER_TORSO|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT + burn_state = FIRE_PROOF /obj/item/clothing/under/acj name = "administrative cybernetic jumpsuit" @@ -163,6 +164,7 @@ max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT slowdown = -10 siemens_coefficient = 0 + burn_state = LAVA_PROOF /obj/item/clothing/under/johnny name = "johnny~~ jumpsuit" @@ -334,6 +336,7 @@ item_state = "gladiator" item_color = "gladiator" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + burn_state = FIRE_PROOF //dress @@ -467,6 +470,7 @@ item_color = "roman" item_state = "armor" strip_delay = 100 + burn_state = FIRE_PROOF /obj/item/clothing/under/maid name = "maid costume" diff --git a/code/modules/computer3/computers/camera.dm b/code/modules/computer3/computers/camera.dm index cb31379a59f..070015f4dc4 100644 --- a/code/modules/computer3/computers/camera.dm +++ b/code/modules/computer3/computers/camera.dm @@ -181,7 +181,8 @@ //proc/camera_list(var/datum/file/camnet_key/key) get_machines(var/datum/file/camnet_key/key) - if(!computer || computer.z > 6) + // TODO: Tie into space manager + if(!computer || computer.z > ZLEVEL_DERELICT) return null var/list/L = list() diff --git a/code/modules/computer3/computers/cloning.dm b/code/modules/computer3/computers/cloning.dm deleted file mode 100644 index 73978ad6aed..00000000000 --- a/code/modules/computer3/computers/cloning.dm +++ /dev/null @@ -1,363 +0,0 @@ -/obj/machinery/computer3/cloning - default_prog = /datum/file/program/cloning - spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/storage/removable,/obj/item/part/computer/networking/prox) - -/datum/file/program/cloning - name = "cloning console" - desc = "Connects to cloning machinery through the local network." - active_state = "dna_old" - - req_access = list(access_heads) //Only used for record deletion right now. - - var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. - var/obj/machinery/clonepod/pod1 = null //Linked cloning pod. - - var/temp = "Inactive" - var/scantemp_ckey - var/scantemp = "Ready to Scan" - var/menu = 1 //Which menu screen to display - var/list/records = list() - var/datum/data/record/active_record = null - var/loading = 0 // Nice loading text - var/has_disk = 0 - - proc/updatemodules() - if(!computer.net) return - - if(scanner && pod1) - if(!computer.net.verify_machine(scanner)) - scanner = null - if(!computer.net.verify_machine(pod1)) - pod1 = null - - if(!scanner || !pod1) - var/list/nearby = computer.net.get_machines() - scanner = locate(/obj/machinery/dna_scannernew) in nearby - pod1 = locate(/obj/machinery/clonepod) in nearby - - if(pod1) - pod1.connected = src // Some variable the pod needs - - proc/ScanningMenu() - if(isnull(scanner)) - return "ERROR: No Scanner detected!
    " - - var/dat = "

    Scanner Functions

    " - dat += "
    " - - if(!scanner.occupant) - dat += "Scanner Unoccupied" - else if(loading) - dat += "[scanner.occupant] => Scanning..." - else - if(scanner.occupant.ckey != scantemp_ckey) - scantemp = "Ready to Scan" - scantemp_ckey = scanner.occupant.ckey - dat += "[scanner.occupant] => [scantemp]" - - dat += "
    " - - if(scanner.occupant) - dat += topic_link(src,"scan","Start Scan") + "
    " - if(scanner.locked) - dat += topic_link(src,"lock","Unlock Scanner") - else - dat += topic_link(src,"lock","Lock Scanner") - else - dat += fake_link("Start Scan") - - // Footer - dat += "

    Database Functions

    " - if(records.len > 0) - dat += topic_link(src,"menu=2","View Records ([records.len])") + "
    " - else - dat += fake_link("View Records (0)") - - if(has_disk) - dat += topic_link(src,"eject_disk","Eject Disk") + "
    " - return dat - - proc/RecordsList() - var/dat = "

    Current records

    " - to_chat(dat += topic_link(src,"menu=1",", Back") + "

    ") - for(var/datum/data/record/R in records) - dat += "

    [R.fields["name"]]

    Scan ID [R.fields["id"]] " + topic_link(src,"view_rec=\ref[R]","View Record") - return dat - - proc/ShowRecord() - var/dat = "

    Selected Record

    " - to_chat(dat += topic_link(src,"menu=2",", Back") + "

    ") - - if(!active_record) - dat += "Record not found." - else - dat += "

    [active_record.fields["name"]]

    " - dat += "Scan ID [active_record.fields["id"]] [topic_link(src,"clone","Clone")]
    " - - var/obj/item/weapon/implant/health/H = locate(active_record.fields["imp"]) - - if((H) && (istype(H))) - dat += "Health Implant Data:
    [H.sensehealth()]

    " - else - dat += "Unable to locate Health Implant.

    " - - dat += "Unique Identifier:
    [active_record.fields["UI"]]
    " - dat += "Structural Enzymes:
    [active_record.fields["SE"]]
    " - - if(has_disk) - dat += "
    " - dat += "

    Inserted Disk

    " - dat += "Contents: " - if(computer.floppy.inserted.files.len == 0) - dat += "Empty" - else - for(var/datum/file/data/genome/G in computer.floppy.inserted.files) - dat += topic_link(src,"loadfile=\ref[G]","[G.name]") + "
    " - - dat += "

    Save to Disk:
    " - dat += topic_link(src,"save_disk=ue","Unique Identifier + Unique Enzymes") + "
    " - dat += topic_link(src,"save_disk=ui","Unique Identifier") + "
    " - dat += topic_link(src,"save_disk=se","Structural Enzymes") + "
    " - dat += "
    " - - dat += "[topic_link(src,"del_rec","Delete Record")]" - return dat - proc/ConfirmDelete() - var/dat = "[temp]
    " - dat += "

    Confirm Record Deletion

    " - - dat += "[topic_link(src,"del_rec","Scan card to confirm")]
    " - dat += "[topic_link(src,"menu=3","Cancel")]" - return dat - - interact() - if(!interactable()) - return - - updatemodules() - - var/dat = "" - dat += topic_link(src,"refresh","Refresh") - dat += "

    Cloning Pod Status

    " - dat += "
    [temp] 
    " - - has_disk = (computer.floppy && computer.floppy.inserted) - if(!active_record && menu > 2) - menu = 2 - - switch(menu) - if(1) - dat += ScanningMenu() - - if(2) - dat += RecordsList() - - if(3) - dat += ShowRecord() - - if(4) - dat = ConfirmDelete() // not (+=), this is how it used to be, just putting it in a function - - if(!popup) - popup = new(usr, "\ref[computer]", "Cloning System Control") - popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state)) - - popup.set_content(dat) - popup.open() - return - - Topic(var/href, var/list/href_list) - if(loading || !interactable()) - return - - if(href_list["menu"]) - menu = text2num(href_list["menu"]) - else if(("scan" in href_list) && !isnull(scanner)) - scantemp = "" - - loading = 1 - computer.updateUsrDialog() - - spawn(20) - scan_mob(scanner.occupant) - - loading = 0 - computer.updateUsrDialog() - - - //No locking an open scanner. - else if(("lock" in href_list) && !isnull(scanner)) - if((!scanner.locked) && (scanner.occupant)) - scanner.locked = 1 - else - scanner.locked = 0 - - else if("view_rec" in href_list) - active_record = locate(href_list["view_rec"]) - if(istype(active_record,/datum/data/record)) - if( !active_record.fields["ckey"] || active_record.fields["ckey"] == "" ) - del(active_record) - temp = "Record Corrupt" - else - menu = 3 - else - active_record = null - temp = "Record missing." - - else if("del_rec" in href_list) - if((!active_record) || (menu < 3)) - return - if(menu == 3) //If we are viewing a record, confirm deletion - temp = "Delete record?" - menu = 4 - - else if(menu == 4) - var/obj/item/weapon/card/id/C = usr.get_active_hand() - if(istype(C)||istype(C, /obj/item/device/pda)) - if(check_access(C)) - temp = "[active_record.fields["name"]] => Record deleted." - records.Remove(active_record) - del(active_record) - menu = 2 - else - temp = "Access Denied." - - else if("eject_disk" in href_list) - if(computer.floppy) - computer.floppy.eject_disk() - - else if("loadfile" in href_list) - - var/datum/file/data/genome/G = locate(href_list["loadfile"]) in computer.floppy.files - if(!istype(G)) - temp = "Load error." - computer.updateUsrDialog() - return - switch(G.type) - if(/datum/file/data/genome/UI) - active_record.fields["UI"] = G.content - if(/datum/file/data/genome/UE) - active_record.fields["name"] = G.real_name - if(/datum/file/data/genome/SE) - active_record.fields["SE"] = G.content - if(/datum/file/data/genome/cloning) - active_record = G:record - else if("savefile" in href_list) - if(!active_record || !computer || !computer.floppy) - temp = "Save error." - computer.updateUsrDialog() - return - var/rval = 0 - switch(href_list["save_disk"]) - if("ui") - var/datum/file/data/genome/UI/ui = new - ui.content = active_record.fields["UI"] - ui.real_name = active_record.fields["name"] - rval = computer.floppy.addfile(ui) - if("ue") - var/datum/file/data/genome/UI/UE/ui = new - ui.content = active_record.fields["UI"] - ui.real_name = active_record.fields["name"] - rval = computer.floppy.addfile(ui) - if("se") - var/datum/file/data/genome/SE/se = new - se.content = active_record.fields["SE"] - se.real_name = active_record.fields["name"] - rval = computer.floppy.addfile(se) - if("clone") - var/datum/file/data/genome/cloning/c = new - c.record = active_record - c.real_name = active_record.fields["name"] - rval = computer.floppy.addfile(c) - if(!rval) - temp = "Disk write error." - - else if("refresh" in href_list) - computer.updateUsrDialog() - - else if("clone" in href_list) - //Look for that player! They better be dead! - if(active_record) - //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. - if(!pod1) - temp = "No Clonepod detected." - else if(pod1.occupant) - temp = "Clonepod is currently occupied." - else if(pod1.mess) - temp = "Clonepod malfunction." - else if(!config.revival_cloning) - temp = "Unable to initiate cloning cycle." - else if(pod1.growclone(active_record.fields["ckey"], active_record.fields["name"], active_record.fields["UI"], active_record.fields["SE"], active_record.fields["mind"], active_record.fields["mrace"])) - temp = "[active_record.fields["name"]] => Cloning cycle in progress..." - records.Remove(active_record) - del(active_record) - menu = 1 - else - temp = "[active_record.fields["name"]] => Initialisation failure." - - else - temp = "Data corruption." - - computer.add_fingerprint(usr) - computer.updateUsrDialog() - return - - proc/scan_mob(mob/living/carbon/human/subject as mob) - if((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna)) - scantemp = "Unable to locate valid genetic data." - return - if(!getbrain(subject)) - scantemp = "No signs of intelligence detected." - return - if(subject.suiciding == 1) - scantemp = "Subject's brain is not responding to scanning stimuli." - return - if((!subject.ckey) || (!subject.client)) - scantemp = "Mental interface failure." - return - if(NOCLONE in subject.mutations) - scantemp = "Mental interface failure." - return - if(!isnull(find_record(subject.ckey))) - scantemp = "Subject already in database." - return - - subject.dna.check_integrity() - - var/datum/data/record/R = new /datum/data/record( ) - if(subject.dna) - R.fields["mrace"] = subject.dna.mutantrace - R.fields["UI"] = subject.dna.uni_identity - R.fields["SE"] = subject.dna.struc_enzymes - else - R.fields["mrace"] = null - R.fields["UI"] = null - R.fields["SE"] = null - R.fields["ckey"] = subject.ckey - R.fields["name"] = subject.real_name - R.fields["id"] = copytext(md5(subject.real_name), 2, 6) - - - - //Add an implant if needed - var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) - if(isnull(imp)) - imp = new /obj/item/weapon/implant/health(subject) - imp.implanted = subject - R.fields["imp"] = "\ref[imp]" - //Update it if needed - else - R.fields["imp"] = "\ref[imp]" - - if(!isnull(subject.mind)) //Save that mind so traitors can continue traitoring after cloning. - R.fields["mind"] = "\ref[subject.mind]" - - records += R - scantemp = "Subject successfully scanned." - -//Find a specific record by key. - proc/find_record(var/find_key) - for(var/datum/data/record/R in records) - if(R.fields["ckey"] == find_key) - return R - return null diff --git a/code/modules/computer3/computers/communications.dm b/code/modules/computer3/computers/communications.dm index 2f02bdcfdb3..d6575d3c143 100644 --- a/code/modules/computer3/computers/communications.dm +++ b/code/modules/computer3/computers/communications.dm @@ -59,6 +59,7 @@ Topic(var/href, var/list/href_list) if(!interactable() || !computer.radio || ..(href,href_list) ) return + // TODO: Tie into space manager if(!(computer.z in config.station_levels)) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return diff --git a/code/modules/computer3/computers/law.dm b/code/modules/computer3/computers/law.dm index d75a016f680..7534aa65932 100644 --- a/code/modules/computer3/computers/law.dm +++ b/code/modules/computer3/computers/law.dm @@ -24,7 +24,8 @@ attackby(obj/item/weapon/aiModule/module as obj, mob/user as mob, params) - if(user.z > 6) + // TODO: Tie into space manager + if(user.z > ZLEVEL_DERELICT) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return if(istype(module, /obj/item/weapon/aiModule)) diff --git a/code/modules/computer3/computers/medical.dm b/code/modules/computer3/computers/medical.dm index 27002c264c2..6e96b6728e7 100644 --- a/code/modules/computer3/computers/medical.dm +++ b/code/modules/computer3/computers/medical.dm @@ -49,7 +49,8 @@ scan = computer.cardslot.reader if(!interactable()) return - if(computer.z > 6) + // TODO: Tie into space manager + if(computer.z > ZLEVEL_DERELICT) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return var/dat diff --git a/code/modules/computer3/computers/prisoner.dm b/code/modules/computer3/computers/prisoner.dm index b38b376abf5..75b2302991f 100644 --- a/code/modules/computer3/computers/prisoner.dm +++ b/code/modules/computer3/computers/prisoner.dm @@ -43,6 +43,7 @@ if(!T.implanted) continue var/loc_display = "Unknown" var/mob/living/carbon/M = T.imp_in + // TODO: Tie into space manager if(M.z == ZLEVEL_STATION && !istype(M.loc, /turf/space)) var/turf/mob_loc = get_turf(M) loc_display = mob_loc.loc @@ -98,5 +99,3 @@ interact() return - - diff --git a/code/modules/computer3/computers/prisonshuttle.dm b/code/modules/computer3/computers/prisonshuttle.dm deleted file mode 100644 index e7dd5c650ac..00000000000 --- a/code/modules/computer3/computers/prisonshuttle.dm +++ /dev/null @@ -1,242 +0,0 @@ -//Config stuff -#define PRISON_MOVETIME 150 //Time to station is milliseconds. -#define PRISON_STATION_AREATYPE "/area/shuttle/prison/station" //Type of the prison shuttle area for station -#define PRISON_DOCK_AREATYPE "/area/shuttle/prison/prison" //Type of the prison shuttle area for dock - -var/prison_shuttle_moving_to_station = 0 -var/prison_shuttle_moving_to_prison = 0 -var/prison_shuttle_at_station = 0 -var/prison_shuttle_can_send = 1 -var/prison_shuttle_time = 0 -var/prison_shuttle_timeleft = 0 - -/obj/machinery/computer3/prison_shuttle - name = "Prison Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_security) - circuit = "/obj/item/part/board/circuit/prison_shuttle" - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - var/prison_break = 0 - - - attackby(I as obj, user as mob, params) - return src.attack_hand(user) - - - attack_ai(var/mob/user as mob) - return src.attack_hand(user) - - - attack_paw(var/mob/user as mob) - return src.attack_hand(user) - - - attackby(I as obj, user as mob, params) - if(istype(I, /obj/item/tool/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20, target = src)) - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/part/board/circuit/prison_shuttle/M = new /obj/item/part/board/circuit/prison_shuttle( A ) - for(var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.anchored = 1 - - if(src.stat & BROKEN) - to_chat(user, "\blue The broken glass falls out.") - new /obj/item/trash/shard( src.loc ) - A.state = 3 - A.icon_state = "3" - else - to_chat(user, "\blue You disconnect the monitor.") - A.state = 4 - A.icon_state = "4" - - del(src) - else if(istype(I,/obj/item/card/emag) && (!hacked)) - hacked = 1 - to_chat(user, "\blue You disable the lock.") - else - return src.attack_hand(user) - - - attack_hand(var/mob/user as mob) - if(!src.allowed(user) && (!hacked)) - to_chat(user, "\red Access Denied.") - return - if(prison_break) - to_chat(user, "\red Unable to locate shuttle.") - return - if(..()) - return - user.set_machine(src) - post_signal("prison") - var/dat - if(src.temp) - dat = src.temp - else - dat += {"Location: [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "Moving to station ([prison_shuttle_timeleft] Secs.)":prison_shuttle_at_station ? "Station":"Dock"]
    - [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "\n*Shuttle already called*
    \n
    ":prison_shuttle_at_station ? "\nSend to Dock
    \n
    ":"\nSend to Station
    \n
    "] - \nClose"} - - //user << browse(dat, "window=computer;size=575x450") - //onclose(user, "computer") - var/datum/browser/popup = new(user, "computer", name, 575, 450) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - - - Topic(href, href_list) - if(..()) - return - - if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - if(href_list["sendtodock"]) - if(!prison_can_move()) - to_chat(usr, "\red The prison shuttle is unable to leave.") - return - if(!prison_shuttle_at_station|| prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - post_signal("prison") - to_chat(usr, "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds.") - src.temp += "Shuttle sent.

    OK" - src.updateUsrDialog() - prison_shuttle_moving_to_prison = 1 - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - - else if(href_list["sendtostation"]) - if(!prison_can_move()) - to_chat(usr, "\red The prison shuttle is unable to leave.") - return - if(prison_shuttle_at_station || prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - post_signal("prison") - to_chat(usr, "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds.") - src.temp += "Shuttle sent.

    OK" - src.updateUsrDialog() - prison_shuttle_moving_to_station = 1 - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - - else if(href_list["mainmenu"]) - src.temp = null - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - - - proc/prison_can_move() - if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return 0 - else return 1 - -/* - proc/prison_break() - switch(prison_break) - if(0) - if(!prison_shuttle_at_station || prison_shuttle_moving_to_prison) return - - prison_shuttle_moving_to_prison = 1 - prison_shuttle_at_station = prison_shuttle_at_station - - if(!prison_shuttle_moving_to_prison || !prison_shuttle_moving_to_station) - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - prison_break = 1 - if(1) - prison_break = 0 -*/ - - proc/post_signal(var/command) - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1311) - if(!frequency) return - var/datum/signal/status_signal = new - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - frequency.post_signal(src, status_signal) - return - - - proc/prison_process() - while(prison_shuttle_time - world.timeofday > 0) - var/ticksleft = prison_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - prison_shuttle_time = world.timeofday + 10 // midnight rollover - - prison_shuttle_timeleft = (ticksleft / 10) - sleep(5) - prison_shuttle_moving_to_station = 0 - prison_shuttle_moving_to_prison = 0 - - switch(prison_shuttle_at_station) - - if(0) - prison_shuttle_at_station = 1 - if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - - if(!prison_can_move()) - to_chat(usr, "\red The prison shuttle is unable to leave.") - return - - var/area/start_location = locate(/area/shuttle/prison/prison) - var/area/end_location = locate(/area/shuttle/prison/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - start_location.move_contents_to(end_location) - - if(1) - prison_shuttle_at_station = 0 - if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - - if(!prison_can_move()) - to_chat(usr, "\red The prison shuttle is unable to leave.") - return - - var/area/start_location = locate(/area/shuttle/prison/station) - var/area/end_location = locate(/area/shuttle/prison/prison) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - start_location.move_contents_to(end_location) - return \ No newline at end of file diff --git a/code/modules/computer3/computers/robot.dm b/code/modules/computer3/computers/robot.dm index 9e9e4b29fac..a728c8993bf 100644 --- a/code/modules/computer3/computers/robot.dm +++ b/code/modules/computer3/computers/robot.dm @@ -31,7 +31,8 @@ interact() - if(!interactable() || computer.z > 6) + // TODO: Tie into space manager + if(!interactable() || computer.z > ZLEVEL_DERELICT) return var/dat if(src.temp) @@ -206,6 +207,3 @@ interact() return - - - diff --git a/code/modules/computer3/computers/security.dm b/code/modules/computer3/computers/security.dm index ce6184178bf..d974101b33f 100644 --- a/code/modules/computer3/computers/security.dm +++ b/code/modules/computer3/computers/security.dm @@ -57,7 +57,8 @@ if(!interactable()) return - if(computer.z > 6) + // TODO: Tie into space manager + if(computer.z > ZLEVEL_DERELICT) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return var/dat diff --git a/code/modules/computer3/computers/shuttle.dm b/code/modules/computer3/computers/shuttle.dm deleted file mode 100644 index 70bdb133137..00000000000 --- a/code/modules/computer3/computers/shuttle.dm +++ /dev/null @@ -1,76 +0,0 @@ -/* - This may not migrate to C3. It's basically a machine in the guise of a computer; - there is nothing interactive about it. -*/ - -/obj/machinery/computer3/shuttle - name = "Shuttle" - desc = "For shuttle control." - icon_state = "shuttle" - var/auth_need = 3.0 - var/list/authorized = list( ) - - - attackby(var/obj/item/card/W as obj, var/mob/user as mob, params) - if(stat & (BROKEN|NOPOWER)) return - if((!( istype(W, /obj/item/card) ) || !( ticker ) || emergency_shuttle.location != 1 || !( user ))) return - if(istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda)) - if(istype(W, /obj/item/device/pda)) - var/obj/item/device/pda/pda = W - W = pda.id - if(!W:access) //no access - to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return - - var/list/cardaccess = W:access - if(!istype(cardaccess, /list) || !cardaccess.len) //no access - to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return - - if(!(access_heads in W:access)) //doesn't have this access - to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return 0 - - var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort") - if(emergency_shuttle.location != 1 && user.get_active_hand() != W) - return 0 - switch(choice) - if("Authorize") - src.authorized -= W:registered_name - src.authorized += W:registered_name - if(src.auth_need - src.authorized.len > 0) - message_admins("[key_name_admin(user)] has authorized early shuttle launch") - log_game("[user.ckey] has authorized early shuttle launch") - to_chat(world, text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) - else - message_admins("[key_name_admin(user)] has launched the shuttle") - log_game("[user.ckey] has launched the shuttle early") - to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") - emergency_shuttle.online = 1 - emergency_shuttle.settimeleft(10) - //src.authorized = null - del(src.authorized) - src.authorized = list( ) - - if("Repeal") - src.authorized -= W:registered_name - to_chat(world, text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) - - if("Abort") - to_chat(world, "\blue All authorizations to shorting time for shuttle launch have been revoked!") - src.authorized.len = 0 - src.authorized = list( ) - return - - emag_act(user as mob) - if(!emagged) - var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel") - - if(!emagged && emergency_shuttle.location == 1) - switch(choice) - if("Launch") - to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") - emergency_shuttle.settimeleft( 10 ) - emagged = 1 - if("Cancel") - return diff --git a/code/modules/computer3/computers/specops_shuttle.dm b/code/modules/computer3/computers/specops_shuttle.dm deleted file mode 100644 index fa64036857d..00000000000 --- a/code/modules/computer3/computers/specops_shuttle.dm +++ /dev/null @@ -1,246 +0,0 @@ -//Config stuff -#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station -#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock - -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 - -/obj/machinery/computer3/specops_shuttle - name = "Spec. Ops. Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - -/proc/specops_process() - var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - announcer.say(message) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - announcer.say(message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if(!specops_can_move()) - to_chat(usr, "\red The Special Operations shuttle is unable to leave.") - return - - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T - to_chat(M, "\red You have arrived to [station_name]. Commence operation!") - -/proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 - else return 1 - -/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob, params) - return attack_hand(user) - -/obj/machinery/computer3/specops_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/specops_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob, params) - if(istype(I,/obj/item/card/emag)) - to_chat(user, "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - else - return attack_hand(user) - -/obj/machinery/computer3/specops_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) - to_chat(user, "\red Access Denied.") - return - - if(sent_strike_team == 0) - to_chat(usr, "\red The strike team has not yet deployed.") - return - - if(..()) - return - - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - dat += {" - Location: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
    - [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
    \n
    ":specops_shuttle_at_station ? "\nShuttle Offline
    \n
    ":"\nDepart to [station_name]
    \n
    "] - \nClose"} - - //user << browse(dat, "window=computer;size=575x450") - //onclose(user, "computer") - var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/machinery/computer3/specops_shuttle/Topic(href, href_list) - if(..()) - return - - if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - if(href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - to_chat(usr, "\blue Central Command will not allow the Special Operations shuttle to return.") - return - - else if(href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if(!specops_can_move()) - to_chat(usr, "\red The Special Operations shuttle is unable to leave.") - return - - to_chat(usr, "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds.") - - temp += "Shuttle departing.

    OK" - updateUsrDialog() - - var/area/centcom/specops/special_ops = locate() - if(special_ops) - special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if(href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return \ No newline at end of file diff --git a/code/modules/computer3/computers/syndicate_shuttle.dm b/code/modules/computer3/computers/syndicate_shuttle.dm deleted file mode 100644 index 5585f4fff0a..00000000000 --- a/code/modules/computer3/computers/syndicate_shuttle.dm +++ /dev/null @@ -1,103 +0,0 @@ -#define SYNDICATE_SHUTTLE_MOVE_TIME 240 -#define SYNDICATE_SHUTTLE_COOLDOWN 200 - -/obj/machinery/computer3/syndicate_station - name = "syndicate shuttle terminal" - icon = 'icons/obj/computer.dmi' - icon_state = "syndishuttle" - req_access = list(access_syndicate) - var/area/curr_location - var/moving = 0 - var/lastMove = 0 - - -/obj/machinery/computer3/syndicate_station/New() - curr_location= locate(/area/syndicate_station/start) - - -/obj/machinery/computer3/syndicate_station/proc/syndicate_move_to(area/destination as area) - if(moving) return - if(lastMove + SYNDICATE_SHUTTLE_COOLDOWN > world.time) return - var/area/dest_location = locate(destination) - if(curr_location == dest_location) return - - moving = 1 - lastMove = world.time - - if(curr_location.z != dest_location.z) - var/area/transit_location = locate(/area/syndicate_station/transit) - curr_location.move_contents_to(transit_location) - curr_location = transit_location - sleep(SYNDICATE_SHUTTLE_MOVE_TIME) - - curr_location.move_contents_to(dest_location) - curr_location = dest_location - moving = 0 - return 1 - - -/obj/machinery/computer3/syndicate_station/attackby(obj/item/I as obj, mob/user as mob, params) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_station/attack_ai(mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_station/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_station/attack_hand(mob/user as mob) - if(!allowed(user)) - to_chat(user, "\red Access Denied") - return - - user.set_machine(src) - - var/dat = {"Location: [curr_location]
    - Ready to move[max(lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
    - Syndicate Space
    - North West of SS13 | - North of SS13 | - North East of SS13
    - South West of SS13 | - South of SS13 | - South East of SS13
    - North East of the Mining Asteroid
    - Close"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - - -/obj/machinery/computer3/syndicate_station/Topic(href, href_list) - if(!isliving(usr)) return - var/mob/living/user = usr - - if(in_range(src, user) || istype(user, /mob/living/silicon)) - user.set_machine(src) - - if(href_list["syndicate"]) - syndicate_move_to(/area/syndicate_station/start) - else if(href_list["station_nw"]) - syndicate_move_to(/area/syndicate_station/northwest) - else if(href_list["station_n"]) - syndicate_move_to(/area/syndicate_station/north) - else if(href_list["station_ne"]) - syndicate_move_to(/area/syndicate_station/northeast) - else if(href_list["station_sw"]) - syndicate_move_to(/area/syndicate_station/southwest) - else if(href_list["station_s"]) - syndicate_move_to(/area/syndicate_station/south) - else if(href_list["station_se"]) - syndicate_move_to(/area/syndicate_station/southeast) -// else if(href_list["commssat"]) -// syndicate_move_to(/area/syndicate_station/commssat) - else if(href_list["mining"]) - syndicate_move_to(/area/syndicate_station/mining) - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer3/syndicate_station/bullet_act(var/obj/item/projectile/Proj) - visible_message("[Proj] ricochets off [src]!") //let's not let them fuck themselves in the rear \ No newline at end of file diff --git a/code/modules/computer3/computers/syndicate_specops_shuttle.dm b/code/modules/computer3/computers/syndicate_specops_shuttle.dm deleted file mode 100644 index c9a61b2dfad..00000000000 --- a/code/modules/computer3/computers/syndicate_specops_shuttle.dm +++ /dev/null @@ -1,259 +0,0 @@ -//Config stuff -#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is deciseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station -#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock - -var/syndicate_elite_shuttle_moving_to_station = 0 -var/syndicate_elite_shuttle_moving_to_mothership = 0 -var/syndicate_elite_shuttle_at_station = 0 -var/syndicate_elite_shuttle_can_send = 1 -var/syndicate_elite_shuttle_time = 0 -var/syndicate_elite_shuttle_timeleft = 0 - -/obj/machinery/computer3/syndicate_elite_shuttle - name = "Elite Syndicate Squad Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "syndishuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - -/proc/syndicate_elite_process() - var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work. - var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - announcer.say(message) - // message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - // announcer.say(message) - - while(syndicate_elite_shuttle_time - world.timeofday > 0) - var/ticksleft = syndicate_elite_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - syndicate_elite_shuttle_time = world.timeofday // midnight rollover - syndicate_elite_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - announcer.say(message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - syndicate_elite_shuttle_moving_to_station = 0 - syndicate_elite_shuttle_moving_to_mothership = 0 - - syndicate_elite_shuttle_at_station = 1 - if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - - if(!syndicate_elite_can_move()) - to_chat(usr, "\red The Syndicate Elite shuttle is unable to leave.") - return - - sleep(600) -/* - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in elite_squad) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in elite_squad) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in elite_squad) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - */ - elite_squad.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. -/* - var/obj/explosionmarker = locate("Syndicate Breach Area") - if(explosionmarker) - var/turf/simulated/T = explosionmarker.loc - if(T) - explosion(T,4,6,8,10,0) - - sleep(40) -// proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1) - -*/ - var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership) - var/area/end_location = locate(/area/shuttle/syndicate_elite/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs = T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T - to_chat(M, "\red You have arrived to [station_name]. Commence operation!") - -/proc/syndicate_elite_can_move() - if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0 - else return 1 - -/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob, params) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_elite_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_elite_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob, params) - if(istype(I,/obj/item/card/emag)) - to_chat(user, "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - else - return attack_hand(user) - -/obj/machinery/computer3/syndicate_elite_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) - to_chat(user, "\red Access Denied.") - return - -// if(sent_syndicate_strike_team == 0) -// to_chat(usr, "\red The strike team has not yet deployed.") -// return - - if(..()) - return - - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - dat = {"Location: [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]
    - [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
    \n
    ":syndicate_elite_shuttle_at_station ? "\nShuttle Offline
    \n
    ":"\nDepart to [station_name]
    \n
    "] - \nClose"} - - //user << browse(dat, "window=computer;size=575x450") - //onclose(user, "computer") - var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/machinery/computer3/syndicate_elite_shuttle/Topic(href, href_list) - if(..()) - return - - if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - if(href_list["sendtodock"]) - if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - - to_chat(usr, "\blue The Syndicate will not allow the Elite Squad shuttle to return.") - return - - else if(href_list["sendtostation"]) - if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - - if(!specops_can_move()) - to_chat(usr, "\red The Syndicate Elite shuttle is unable to leave.") - return - - to_chat(usr, "\blue The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds.") - - temp = "Shuttle departing.

    OK" - updateUsrDialog() - - var/area/syndicate_mothership/elite_squad/elite_squad = locate() - if(elite_squad) - elite_squad.readyalert()//Trigger alarm for the spec ops area. - syndicate_elite_shuttle_moving_to_station = 1 - - syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME - spawn(0) - syndicate_elite_process() - - - else if(href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return \ No newline at end of file diff --git a/code/modules/computer3/networking.dm b/code/modules/computer3/networking.dm index f31f4516c2c..0fc1c966d1c 100644 --- a/code/modules/computer3/networking.dm +++ b/code/modules/computer3/networking.dm @@ -105,6 +105,7 @@ for(var/obj/O in radio_connection.devices) if(istype(O,typekey)) T = get_turf(O) + // TODO: Tie into space manager if(istype(O) && (subspace || (O.z == z_level))) // radio does not work across z-levels result |= O return result @@ -232,4 +233,3 @@ if(C.d1 == 0 && (C.powernet == P)) return 1 return 0 - diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index 5ea69f25c55..cc07dd248b4 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -125,6 +125,7 @@ log transactions if(get_dist(src,user) <= 1) //check to see if the user has low security enabled scan_user(user) + add_fingerprint(user) //js replicated from obj/machinery/computer/card var/dat = {"

    Nanotrasen Automatic Teller Machine

    diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index 1293d92b2b3..920ce488cb4 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -292,6 +292,6 @@ "} P.info = text - state("The terminal prints out a report.") + visible_message("[src] prints out a report.") return 1 diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 927db3c3668..b6313a77a40 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -17,6 +17,7 @@ /datum/event/alien_infestation/start() var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + // TODO: Tie into space manager if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded) if(temp_vent.parent.other_atmosmch.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology vents += temp_vent @@ -34,4 +35,3 @@ spawncount-- successSpawn = 1 - diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm index 13d7478aab3..f7db50694d6 100644 --- a/code/modules/events/anomaly_bluespace.dm +++ b/code/modules/events/anomaly_bluespace.dm @@ -19,6 +19,7 @@ var/obj/item/device/radio/beacon/chosen var/list/possible = list() for(var/obj/item/device/radio/beacon/W in world) + // TODO: Tie into space manager if(!(W.z in config.station_levels)) continue possible += W diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index 05110a7f0ce..e51ad46f61a 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -18,7 +18,8 @@ /datum/event/brand_intelligence/start() for(var/obj/machinery/vending/V in machines) - if(V.z != 1) continue + // TODO: Tie into space manager + if(V.z != ZLEVEL_STATION) continue vendingMachines.Add(V) if(!vendingMachines.len) @@ -62,4 +63,4 @@ rebel.shoot_inventory = 1 if(IsMultiple(activeFor, 8)) - originMachine.speak(pick(rampant_speeches)) \ No newline at end of file + originMachine.speak(pick(rampant_speeches)) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index ce6e214053d..0f44bf586ee 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -21,7 +21,8 @@ var/turf/T = get_turf(H) if(!T) continue - if(T.z != 1) + // TODO: Tie into space manager + if(T.z != ZLEVEL_STATION) continue var/foundAlready = 0 // don't infect someone that already has the virus for(var/datum/disease/D in H.viruses) @@ -34,4 +35,4 @@ D = new virus_type() D.carrier = 1 H.AddDisease(D) - break \ No newline at end of file + break diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 20f7f9955eb..17b529f9bda 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -62,7 +62,7 @@ goal = locate(endx, endy, 1) src.x = startx src.y = starty - src.z = 1 + src.z = ZLEVEL_STATION spawn(0) walk_towards(src, goal, 1) return diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 5955d60cbec..deaa1b85aa8 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -149,7 +149,7 @@ var/list/event_last_fired = list() new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Virology Breach", /datum/event/prison_break/virology, 0, list(ASSIGNMENT_MEDICAL = 100)), //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Xenobiology Breach", /datum/event/prison_break/xenobiology, 0, list(ASSIGNMENT_SCIENCE = 100)), - //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 50), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm index ca675306ffa..479a0ea162e 100644 --- a/code/modules/events/grid_check.dm +++ b/code/modules/events/grid_check.dm @@ -22,6 +22,7 @@ for(var/obj/machinery/power/smes/S in machines) var/area/current_area = get_area(S) + // TODO: Tie into space manager if(current_area.type in skipped_areas || !(S.z in config.station_levels)) continue S.last_charge = S.charge @@ -33,8 +34,9 @@ S.update_icon() S.power_change() - for(var/obj/machinery/power/apc/C in world) + for(var/obj/machinery/power/apc/C in apcs) var/area/current_area = get_area(C) + // TODO: Tie into space manager if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels)) continue if(C.cell) @@ -46,14 +48,16 @@ if(announce) command_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') - for(var/obj/machinery/power/apc/C in machines) + for(var/obj/machinery/power/apc/C in apcs) var/area/current_area = get_area(C) + // TODO: Tie into space manager if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels)) continue if(C.cell) C.cell.charge = C.cell.maxcharge for(var/obj/machinery/power/smes/S in machines) var/area/current_area = get_area(S) + // TODO: Tie into space manager if(current_area.type in skipped_areas || !(S.z in config.station_levels)) continue S.charge = S.last_charge @@ -66,7 +70,8 @@ if(announce) command_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') for(var/obj/machinery/power/smes/S in machines) - if(S.z != 1) + // TODO: Tie into space manager + if(S.z != ZLEVEL_STATION) continue S.charge = S.capacity S.output_level = S.output_level_max @@ -74,4 +79,3 @@ S.input_attempt = 1 S.update_icon() S.power_change() - \ No newline at end of file diff --git a/code/modules/events/holidays/Christmas.dm b/code/modules/events/holidays/Christmas.dm index 10a46b0cf51..1d5a4d9e659 100644 --- a/code/modules/events/holidays/Christmas.dm +++ b/code/modules/events/holidays/Christmas.dm @@ -1,5 +1,6 @@ /proc/Christmas_Game_Start() for(var/obj/structure/flora/tree/pine/xmas in world) + // TODO: Tie into space manager if(!(xmas.z in config.station_levels)) continue for(var/turf/simulated/floor/T in orange(1,xmas)) for(var/i=1,i<=rand(1,5),i++) @@ -14,7 +15,7 @@ evil_tree.icon_living = evil_tree.icon_state evil_tree.icon_dead = evil_tree.icon_state evil_tree.icon_gib = evil_tree.icon_state - del(xmas) + qdel(xmas) /obj/item/weapon/toy/xmas_cracker name = "xmas cracker" @@ -40,7 +41,7 @@ "What do you get from eating tree decorations?\n\nTinsilitis!", "What do snowmen wear on their heads?\n\nIce caps!", "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", - "Why doesn’t Santa have any children?\n\nBecause he only comes down the chimney.") + "Why doesn�t Santa have any children?\n\nBecause he only comes down the chimney.") new /obj/item/clothing/head/festive(target.loc) user.update_icons() cracked = 1 @@ -59,4 +60,3 @@ desc = "A crappy paper hat that you are REQUIRED to wear." flags_inv = 0 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - diff --git a/code/modules/events/meaty_ops.dm b/code/modules/events/meaty_ops.dm index d6bdea43393..19263c75f82 100644 --- a/code/modules/events/meaty_ops.dm +++ b/code/modules/events/meaty_ops.dm @@ -1,5 +1,5 @@ /datum/event/meteor_wave/goreop/announce() - var/meteor_declaration = "MeteorOps have declared thier intent to utterly destroy [station_name()] with thier own bodies, and dares the crew to try and stop them." + var/meteor_declaration = "MeteorOps have declared their intent to utterly destroy [station_name()] with their own bodies, and dares the crew to try and stop them." command_announcement.Announce(meteor_declaration, "Declaration of 'War'", 'sound/effects/siren.ogg') /datum/event/meteor_wave/goreop/setup() diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 5afddd49d23..54a2bb41bb9 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -24,6 +24,7 @@ command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg') for(var/area/A in world) + // TODO: Tie into space manager if(!(A.z in config.station_levels) || is_safe_zone(A)) continue A.radiation_alert() @@ -42,6 +43,7 @@ var/turf/T = get_turf(H) if(!T) continue + // TODO: Tie into space manager if(!(T.z in config.station_levels) || is_safe_zone(T.loc)) continue @@ -61,6 +63,7 @@ command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") for(var/area/A in world) + // TODO: Tie into space manager if(!(A.z in config.station_levels) || is_safe_zone(A)) continue A.reset_radiation_alert() diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm index 7837bd61d7c..455312baa99 100644 --- a/code/modules/events/rogue_drones.dm +++ b/code/modules/events/rogue_drones.dm @@ -41,7 +41,7 @@ var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread() sparks.set_up(3, 0, D.loc) sparks.start() - D.z = 2 + D.z = ZLEVEL_CENTCOMM D.has_loot = 0 qdel(D) diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index a628e3130ed..2c46fc8dffa 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -16,6 +16,7 @@ var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + // TODO: Tie into space manager if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded) if(temp_vent.parent.other_atmosmch.len > 50) vents += temp_vent @@ -26,4 +27,4 @@ if(prob(66)) S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/nurse vents -= vent - spawncount-- \ No newline at end of file + spawncount-- diff --git a/code/modules/events/undead.dm b/code/modules/events/undead.dm index 2ff8d05c20a..3399c69c979 100644 --- a/code/modules/events/undead.dm +++ b/code/modules/events/undead.dm @@ -2,13 +2,14 @@ var/spawn_prob = 10 startWhen = 2 announceWhen = 3 - + /datum/event/undead/start() var/datum/event/electrical_storm/RS = new RS.lightsoutAmount = pick(2,2,3) RS.start() RS.kill() for(var/area/A) + // TODO: Tie into space manager if(!(A.z in config.station_levels)) continue //Spook on main station only. if(A.luminosity) continue // if(A.lighting_space) continue @@ -34,7 +35,7 @@ 80;/mob/living/simple_animal/hostile/retaliate/zombie, 60;/mob/living/simple_animal/hostile/retaliate/ghost) new undeadtype(T) - + /datum/event/undead/announce() for(var/mob/living/M in player_list) to_chat(M, "You feel [pick("a chill","a deathly chill","the undead","dirty", "creeped out","afraid","fear")]!") diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index fae640a73cb..de4e62215a8 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -11,6 +11,7 @@ /datum/event/vent_clog/setup() endWhen = rand(25, 100) for(var/obj/machinery/atmospherics/unary/vent_scrubber/temp_vent in machines) + // TODO: Tie into space manager if((temp_vent.loc.z in config.station_levels)) if(temp_vent.parent.other_atmosmch.len > 50) vents += temp_vent diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 16daa8fe7c9..1f3aa1355cd 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -13,10 +13,11 @@ /datum/event/wormholes/start() for(var/turf/simulated/floor/T in world) + // TODO: Tie into space manager if((T.z in config.station_levels)) pick_turfs += T - for(var/i = 1, i <= number_of_wormholes, i++) + for(var/i in 1 to number_of_wormholes) var/turf/T = pick(pick_turfs) wormholes += new /obj/effect/portal/wormhole(T, null, null, -1) @@ -30,9 +31,8 @@ if(T) O.loc = T /datum/event/wormholes/end() - portals.Remove(wormholes) for(var/obj/effect/portal/wormhole/O in wormholes) - O.loc = null + qdel(O) wormholes.Cut() @@ -62,4 +62,4 @@ if(P && isturf(P.loc)) target = P.loc if(!target) return - do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon \ No newline at end of file + do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index aae17abc961..15ce27b7d5c 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -10,6 +10,7 @@ consume_sound = 'sound/items/drink.ogg' possible_transfer_amounts = list(5,10,15,20,25,30,50) volume = 50 + burn_state = FIRE_PROOF /obj/item/weapon/reagent_containers/food/drinks/New() ..() diff --git a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm index ebdd151a4b5..bc1442038e9 100644 --- a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm +++ b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm @@ -10,6 +10,8 @@ lefthand_file = 'icons/goonstation/mob/inhands/items_lefthand.dmi' righthand_file = 'icons/goonstation/mob/inhands/items_righthand.dmi' materials = list(MAT_GLASS=500) + burn_state = FLAMMABLE + burntime = 5 /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/egg)) //breaking eggs @@ -25,6 +27,15 @@ else ..() +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fire_act() + if(!reagents.total_volume) + return + ..() + +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/burn() + reagents.clear_reagents() + extinguish() + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/on_reagent_change() // *scream if(reagents.reagent_list.len > 0) switch(reagents.get_master_reagent_id()) diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm index 3e0cfb8f867..f14c0d19254 100644 --- a/code/modules/food_and_drinks/food.dm +++ b/code/modules/food_and_drinks/food.dm @@ -11,6 +11,7 @@ var/apply_method = "swallow" var/transfer_efficiency = 1.0 var/instant_application = 0 //if we want to bypass the forcedfeed delay + burn_state = FLAMMABLE /obj/item/weapon/reagent_containers/food/New() ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm index 706ea0e367b..381525a13ae 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm @@ -59,8 +59,8 @@ // Burns the food with a chance of starting a fire - for if you try cooking something that's already been cooked that way // if burns = 0 then it'll just tell you that the item is already that foodtype and it would do nothing -// if you wanted a different side effect set burns to 1 and override burn() -/obj/machinery/cooker/proc/burn(mob/user, obj/item/weapon/reagent_containers/props) +// if you wanted a different side effect set burns to 1 and override burn_food() +/obj/machinery/cooker/proc/burn_food(mob/user, obj/item/weapon/reagent_containers/props) var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/burnt = new(get_turf(src)) setRegents(props, burnt) to_chat(user, "You smell burning coming from the [src]!") @@ -130,7 +130,7 @@ return if(istype(I, /obj/item/weapon/reagent_containers/food/snacks)) if(checkCooked(I)) - burn(user, I) + burn_food(user, I) turnoff(I) return var/obj/item/weapon/reagent_containers/food/snacks/newfood = gettype() diff --git a/code/modules/garbage_collection/__gc_info.dm b/code/modules/garbage_collection/__gc_info.dm index 96e3a0ea8dc..be72097a8c9 100644 --- a/code/modules/garbage_collection/__gc_info.dm +++ b/code/modules/garbage_collection/__gc_info.dm @@ -43,9 +43,8 @@ that can't be. There are two main procs involved in this process: /datum/proc/Destroy() This is, effectively, a replacement for Del() (with some exceptions) which is also responsible for nulling out - references to or on the object it is called on. Like Del, the Destroy proc will always be called, even if the object - is getting destroyed by a direct del instead of qdel; in that case, isnull(gcDestroyed) will be true, and some - references can safely be ignored. + references to or on the object it is called on. Unlike Del, the Destroy proc will only be called by qdel; generally, + this should only happen to datums that are no longer referenced by anything, which shouldn't be an issue. The exceptions where Destroy cannot replace Del are for the same non-datum types mentioned under qdel, above. Those should use a Del proc for any necessary cleanup, as a Destroy proc on them will not automatically get called. diff --git a/code/modules/garbage_collection/garbage_collector.dm b/code/modules/garbage_collection/garbage_collector.dm index 95535376f85..29db9198ae4 100644 --- a/code/modules/garbage_collection/garbage_collector.dm +++ b/code/modules/garbage_collection/garbage_collector.dm @@ -92,12 +92,13 @@ var/global/datum/controller/process/garbage_collector/garbageCollector if(isnull(D)) return - if(isnull(garbageCollector)) + if(!istype(D)) // A non-datum was passed into qdel - just delete it outright. + // warning("qdel() passed object of type [D.type]. qdel() can only handle /datum/ types.") del(D) return - if(!istype(D)) // A non-datum was passed into qdel - just delete it outright. - // warning("qdel() passed object of type [D.type]. qdel() can only handle /datum/ types.") + if(isnull(garbageCollector)) + D.Destroy() del(D) return @@ -162,22 +163,5 @@ var/global/datum/controller/process/garbage_collector/garbageCollector tag = null return QDEL_HINT_QUEUE // Garbage Collect everything. -// If something gets deleted directly, make sure its Destroy proc is still called -/datum/Del() - if(isnull(gcDestroyed)) // Not GC'd - try - Destroy() - catch(var/exception/e) - if(istype(e)) - log_runtime(e, src, "Caught by Del() destroying [type]") - else - gcwarning("Del() caught runtime destroying [type]: [e]") - if(del_profiling) - delete_profile(src) - else - if(del_profiling) - delete_profile(src) - return ..() - /proc/gcwarning(msg) log_to_dd("## GC WARNING: [msg]") diff --git a/code/modules/garbage_collection/gc_testing.dm b/code/modules/garbage_collection/gc_testing.dm index 686b39a8542..b1b413a0398 100644 --- a/code/modules/garbage_collection/gc_testing.dm +++ b/code/modules/garbage_collection/gc_testing.dm @@ -13,28 +13,6 @@ log_admin("[key_name(usr)] turned qdel [garbageCollector.del_everything ? "off" : "on"].") message_admins("\blue [key_name_admin(usr)] turned qdel [garbageCollector.del_everything ? "off" : "on"].", 1) -/client/proc/gc_toggle_profiling() - set name = "(GC) Toggle Profiling" - set desc = "Toggle profiling of deletion methods" - set category = "Debug" - - if(!check_rights(R_DEBUG)) - return - - del_profiling = !del_profiling - log_admin("[key_name(usr)] turned deletion profiling [del_profiling ? "on" : "off"].") - message_admins("\blue [key_name_admin(usr)] turned deletion profiling [del_profiling ? "on" : "off"].", 1) - -/client/proc/gc_show_del_report() - set name = "(GC) Show Del Report" - set desc = "Show report of deletions seen while profiling" - set category = "Debug" - - if(!check_rights(R_DEBUG)) - return - - delete_profiler_report() - /client/proc/gc_dump_hdl() set name = "(GC) Hard Del List" set desc = "List types that are hard del()'d by the GC." @@ -51,77 +29,6 @@ for(var/A in gc_hard_del_types) to_chat(usr, "[A]") -// Profiling stuff -var/global/del_profiling = 0 -var/global/list/dels_profiled = list() -var/global/list/gdels_profiled = list() -var/global/list/ghdels_profiled = list() - -/proc/delete_profile(var/datum/D) - if(!ticker || (ticker.current_state < 3)) return - var/code = 0 - var/type = D.type - if(isnull(D.gcDestroyed)) - code = 0 - else if(D.hard_deleted == -1) - code = 0 // A non-queued hard deletion is counted as a straight deletion - else if(D.hard_deleted) - code = 1 - else - code = 2 - switch(code) - if(0) // Directly deleted (skipped the GC queue entirely) - if(!("[type]" in dels_profiled)) - dels_profiled["[type]"] = 0 - - dels_profiled["[type]"] += 1 - if(1) // Hard-deleted by the GC - if(!("[type]" in ghdels_profiled)) - ghdels_profiled["[type]"] = 0 - - ghdels_profiled["[type]"] += 1 - if(2) // qdel'd and garbage collected by BYOND - if(!("[type]" in gdels_profiled)) - gdels_profiled["[type]"] = 0 - - gdels_profiled["[type]"] += 1 - -/proc/delete_profiler_report() - var/dat = "Deletion Profiler Report" - if(dels_profiled.len + gdels_profiled.len + ghdels_profiled.len) - dat += "Direct Deletions
    " - dat += "GC Soft Deletions
    " - dat += "GC Hard Deletions
    " - dat += delete_profiler_sortedlist(dels_profiled, "Direct Deletions", "DD") - dat += delete_profiler_sortedlist(gdels_profiled, "GC Soft Deletions", "SD") - dat += delete_profiler_sortedlist(ghdels_profiled, "GC Hard Deletions", "HD") - else - dat += "(No deletions profiled; listing types that have been hard-deleted by GC)
    " - dat += "" - for(var/A in gc_hard_del_types) - dat += "" - dat += "
    GC Hard Deletion Types
    [A]
    " - usr << browse(dat, "window=delete_profiler_report;size=600x480") - -/proc/delete_profiler_sortedlist(var/list/L, var/header, var/anchorid) - L = L.Copy() - // Yes, this is a terrible sort, but I'm too lazy to find a good one - var/v,i,j,s - for(i = 1 to L.len-1) - s=i - v = L[L[i]] - for(j = i + 1 to L.len) - if(L[L[j]] > v) - s = j - v = L[L[j]] - L.Swap(i,s) - - var/dat = "" - for(var/t in L) - dat +="" - dat += "
    [header]
    [L[t]][t]
    " - return dat - #ifdef TESTING /client/var/running_find_references /datum/var/running_find_references diff --git a/code/modules/holiday/christmas.dm b/code/modules/holiday/christmas.dm index 7dccff585d8..c90e97d60c1 100644 --- a/code/modules/holiday/christmas.dm +++ b/code/modules/holiday/christmas.dm @@ -1,5 +1,6 @@ /datum/holiday/xmas/celebrate() for(var/obj/structure/flora/tree/pine/xmas in world) + // TODO: Tie into space manager if(!(xmas.z in config.station_levels)) continue for(var/turf/simulated/floor/T in orange(1,xmas)) for(var/i=1,i<=rand(1,5),i++) @@ -43,7 +44,7 @@ "What do you get from eating tree decorations?\n\nTinsilitis!", "What do snowmen wear on their heads?\n\nIce caps!", "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", - "Why doesn’t Santa have any children?\n\nBecause he only comes down the chimney.") + "Why doesn�t Santa have any children?\n\nBecause he only comes down the chimney.") new /obj/item/clothing/head/festive(target.loc) user.update_icons() cracked = 1 @@ -62,4 +63,3 @@ desc = "A crappy paper hat that you are REQUIRED to wear." flags_inv = 0 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) - diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 23a5447f1d4..81d489d9da1 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -10,6 +10,7 @@ var/datum/seed/seed var/potency = -1 var/awakening = 0 + burn_state = FLAMMABLE /obj/item/weapon/reagent_containers/food/snacks/grown/New(newloc,planttype) diff --git a/code/modules/hydroponics/grown_inedible.dm b/code/modules/hydroponics/grown_inedible.dm index 39e94160275..d68740eaf47 100644 --- a/code/modules/hydroponics/grown_inedible.dm +++ b/code/modules/hydroponics/grown_inedible.dm @@ -7,6 +7,7 @@ icon = 'icons/obj/weapons.dmi' var/plantname var/potency = 1 + burn_state = FLAMMABLE /obj/item/weapon/grown/New(newloc,planttype) @@ -170,8 +171,11 @@ to_chat(M, "[user] smacks you with a [name]!FLOWER POWER") to_chat(user, " Your [name]'s FLOWER POWER strikes [M]") if(istype(M, /mob/living)) - to_chat(M, "You are heated by the warmth of the of the [name]!") - M.bodytemperature += potency/2 * TEMPERATURE_DAMAGE_COEFFICIENT + to_chat(M, "You are lit on fire from the intense heat of the [name]!") + M.adjust_fire_stacks(potency / 20) + if(M.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(M)] on fire") + log_game("[key_name(user)] set [key_name(M)] on fire") /obj/item/weapon/grown/novaflower/pickup(mob/living/carbon/human/user as mob) if(!user.gloves) diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 57ad87ecbbe..ec7a5aca25f 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -376,6 +376,7 @@ // Bluespace tomato code copied over from grown.dm. if(get_trait(TRAIT_TELEPORTING)) + // TODO: Tie into space manager if(target.z in config.admin_levels) return 1 @@ -828,4 +829,4 @@ display_name = "modified [base_name]" if(2) //Enhanced seed_name = "enhanced [base_name]" - display_name = "enhanced [base_name]" \ No newline at end of file + display_name = "enhanced [base_name]" diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm index 5ba2b4dcfb3..aaa30c3275f 100644 --- a/code/modules/hydroponics/seed_controller.dm +++ b/code/modules/hydroponics/seed_controller.dm @@ -37,11 +37,15 @@ var/global/datum/controller/plants/plant_controller // Set in New(). /datum/controller/plants/New() if(plant_controller && plant_controller != src) log_debug("Rebuilding plant controller.") - del(plant_controller) + qdel(plant_controller) plant_controller = src setup() process() +/datum/controller/plants/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + // Predefined/roundstart varieties use a string key to make it // easier to grab the new variety when mutating. Post-roundstart // and mutant varieties use their uid converted to a string instead. diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm index 1749181b329..244b9fef8f3 100644 --- a/code/modules/hydroponics/seed_packets.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -6,7 +6,7 @@ var/global/list/plant_seed_sprites = list() icon = 'icons/obj/seeds.dmi' icon_state = "blank" w_class = 2 - + burn_state = FLAMMABLE var/seed_type var/datum/seed/seed var/modified = 0 diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 4d58fee8e11..d4ccee6e50f 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -18,28 +18,36 @@ anchored = 1 density = 1 opacity = 1 + burn_state = FLAMMABLE + burntime = 30 var/health = 50 var/tmp/busy = 0 - var/list/valid_types = list(/obj/item/weapon/book, \ - /obj/item/weapon/tome, \ - /obj/item/weapon/spellbook, \ - /obj/item/weapon/storage/bible) + var/list/allowed_books = list(/obj/item/weapon/book, /obj/item/weapon/spellbook, /obj/item/weapon/storage/bible, /obj/item/weapon/tome) //Things allowed in the bookcase /obj/structure/bookcase/initialize() ..() for(var/obj/item/I in loc) - if(is_type_in_list(I, valid_types)) + if(is_type_in_list(I, allowed_books)) I.forceMove(src) update_icon() /obj/structure/bookcase/attackby(obj/O as obj, mob/user as mob, params) if(busy) //So that you can't mess with it while deconstructing return 1 - if(is_type_in_list(O, valid_types)) - user.drop_item() + if(is_type_in_list(O, allowed_books)) + if(!user.drop_item()) + return O.forceMove(src) update_icon() return 1 + else if(istype(O, /obj/item/weapon/storage/bag/books)) + var/obj/item/weapon/storage/bag/books/B = O + for(var/obj/item/T in B.contents) + if(istype(T, /obj/item/weapon/book) || istype(T, /obj/item/weapon/spellbook) || istype(T, /obj/item/weapon/tome) || istype(T, /obj/item/weapon/storage/bible)) + B.remove_from_storage(T, src) + to_chat(user, "You empty [O] into [src].") + update_icon() + return 1 else if(istype(O, /obj/item/weapon/wrench)) user.visible_message("[user] starts disassembling \the [src].", \ "You start disassembling \the [src].") @@ -51,8 +59,6 @@ user.visible_message("[user] disassembles \the [src].", \ "You disassemble \the [src].") busy = 0 - for(var/i = 1 to 5) - new /obj/item/stack/sheet/wood(get_turf(src)) density = 0 qdel(src) else @@ -72,9 +78,6 @@ else if(health <= 0) visible_message("The bookcase is smashed apart!") - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) qdel(src) return ..() @@ -110,10 +113,10 @@ return /obj/structure/bookcase/Destroy() - for(var/i = 1 to 3) + for(var/i in 1 to 5) new /obj/item/stack/sheet/wood(get_turf(src)) for(var/obj/item/I in contents) - if(is_type_in_list(I, valid_types)) + if(is_type_in_list(I, allowed_books)) I.forceMove(get_turf(src)) return ..() @@ -166,6 +169,7 @@ throw_range = 5 w_class = 3 //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) attack_verb = list("bashed", "whacked", "educated") + burn_state = FLAMMABLE var/dat // Actual page content var/due_date = 0 // Game time in 1/10th seconds diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm index 79133de67f0..e134032b131 100644 --- a/code/modules/martial_arts/mimejutsu.dm +++ b/code/modules/martial_arts/mimejutsu.dm @@ -55,8 +55,8 @@ /datum/martial_art/mimejutsu/proc/mimePalm(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!D.stat && !D.stunned && !D.weakened) - D.visible_message("[A] has barely touched [D] with thier palm!", \ - "[A] hovers thier palm over your face!") + D.visible_message("[A] has barely touched [D] with their palm!", \ + "[A] hovers their palm over your face!") var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) D.throw_at(throw_target, 200, 4,A) diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index d3a65e3c0bf..faf11c70825 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -528,7 +528,8 @@ /obj/item/device/wormhole_jaunter/attack_self(mob/user as mob) var/turf/device_turf = get_turf(user) - if(!device_turf||device_turf.z==2||device_turf.z>=7) + // TODO: Tie into space manager + if(!device_turf||device_turf.z==ZLEVEL_CENTCOMM||device_turf.z>=ZLEVEL_EMPTY) to_chat(user, "You're having difficulties getting the [src.name] to work.") return else @@ -536,13 +537,14 @@ var/list/L = list() for(var/obj/item/device/radio/beacon/B in world) var/turf/T = get_turf(B) + // TODO: Tie into space manager if(T.z == ZLEVEL_STATION) L += B if(!L.len) to_chat(user, "The [src.name] failed to create a wormhole.") return var/chosen_beacon = pick(L) - var/obj/effect/portal/wormhole/jaunt_tunnel/J = new /obj/effect/portal/wormhole/jaunt_tunnel(get_turf(src), chosen_beacon) + var/obj/effect/portal/wormhole/jaunt_tunnel/J = new /obj/effect/portal/wormhole/jaunt_tunnel(get_turf(src), chosen_beacon, lifespan=100) try_move_adjacent(J) playsound(src,'sound/effects/sparks4.ogg',50,1) qdel(src) diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index 8972b675e1a..4a2acd645df 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -7,6 +7,8 @@ flags = CONDUCT force = 10.0 throwforce = 0 + burn_state = FLAMMABLE + burntime = 20 w_class = 4 /obj/item/weapon/moneybag/attack_hand(user as mob) diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ore.dm index f5e0f2349be..2a6f5555555 100644 --- a/code/modules/mining/ore.dm +++ b/code/modules/mining/ore.dm @@ -240,6 +240,7 @@ /obj/item/weapon/ore/New() pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 + // TODO: Tie into space manager if(src.z == ZLEVEL_ASTEROID) score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining asteroid (No Clown Planet) diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm index 7e3d3f6c4bf..eab9faf9a7a 100644 --- a/code/modules/mob/dead/observer/login.dm +++ b/code/modules/mob/dead/observer/login.dm @@ -3,5 +3,9 @@ if(ghostimage) ghostimage.icon_state = src.icon_state updateghostimages() + + if(non_respawnable_keys[ckey]) + can_reenter_corpse = 0 + respawnable_list -= src update_interface() \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index b15761d8c57..59c26c640bc 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -129,11 +129,15 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(var/flags = GHOST_CAN_REENTER) if(key) + if(non_respawnable_keys[ckey]) + flags &= ~GHOST_CAN_REENTER var/mob/dead/observer/ghost = new(src, flags) //Transfer safety to observer spawning proc. ghost.timeofdeath = src.timeofdeath //BS12 EDIT respawnable_list -= src if(ghost.can_reenter_corpse) respawnable_list += ghost + else + non_respawnable_keys[ckey] = 1 ghost.key = key if(!(ghost.client && ghost.client.holder) && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! @@ -148,12 +152,28 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set desc = "Relinquish your life and enter the land of the dead." var/mob/M = src + var/warningmsg = null + var/obj/machinery/cryopod/P = istype(loc, /obj/machinery/cryopod) && loc - if(stat == DEAD) + if(P) + if(TOO_EARLY_TO_GHOST) + warningmsg = "It's too early in the shift to enter cryo" + // If it's not too early, we'll skip straight to ghosting out without penalty + else if(suiciding && TOO_EARLY_TO_GHOST) + warningmsg = "You have committed suicide too early in the round" + else if(stat != DEAD) + warningmsg = "You are alive" + else if(non_respawnable_keys[ckey]) + warningmsg = "You have lost your right to respawn" + + if(!warningmsg) ghostize(1) else - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost now, you probably won't be able to rejoin the round! You can't change your mind, so choose wisely!)","Are you sure you want to ghost?","Ghost","Stay in body") - if(response != "Ghost") return //didn't want to ghost after-all + var/response + var/alertmsg = "Are you -sure- you want to ghost?\n([warningmsg]. If you ghost now, you probably won't be able to rejoin the round! You can't change your mind, so choose wisely!)" + response = alert(src, alertmsg,"Are you sure you want to ghost?","Ghost","Stay in body") + if(response != "Ghost") + return //didn't want to ghost after-all resting = 1 var/mob/dead/observer/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. @@ -162,8 +182,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp Morgue = M.loc if(Morgue) Morgue.update() - if(istype(M.loc, /obj/machinery/cryopod)) - var/obj/machinery/cryopod/P = M.loc + if(P) if(!P.control_computer) P.find_control_computer(urgent=1) if(P.control_computer) diff --git a/code/modules/mob/living/carbon/_defines.dm b/code/modules/mob/living/carbon/_defines.dm index 2abbbf91cbc..163ce8f7c8d 100644 --- a/code/modules/mob/living/carbon/_defines.dm +++ b/code/modules/mob/living/carbon/_defines.dm @@ -4,7 +4,7 @@ #define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point #define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point +#define HEAT_DAMAGE_LEVEL_3 10 //Amount of damage applied when your body temperature passes the 1000K point #define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point #define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index aad88276473..ea9dffd3ca0 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -13,6 +13,7 @@ req_access = list(access_robotics) mecha = null//This does not appear to be used outside of reference in mecha.dm. var/silenced = 0 //if set to 1, they can't talk. + var/next_ping_at = 0 /obj/item/device/mmi/posibrain/attack_self(mob/user as mob) @@ -53,6 +54,8 @@ return 0 if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept")) return 0 + if(!O.can_reenter_corpse) + return 0 if(O.client) return 1 return 0 @@ -190,7 +193,11 @@ /obj/item/device/mmi/posibrain/attack_ghost(var/mob/dead/observer/O) if(searching) volunteer(O) - else + return + if(brainmob && brainmob.key) + return // No point pinging a posibrain with a player already inside + if(check_observer(O) && (world.time >= next_ping_at)) + next_ping_at = world.time + (20 SECONDS) var/turf/T = get_turf_or_move(src.loc) for(var/mob/M in viewers(T)) M.show_message("\blue The positronic brain pings softly.") diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 3c18cddb18f..a4381ebf7a6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -551,12 +551,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, visible_message("[src] has thrown [thrown_thing].") newtonian_move(get_dir(target, src)) thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src) -/* -/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - src.IgniteMob() - bodytemperature = max(bodytemperature, BODYTEMP_HEAT_DAMAGE_LIMIT+10) -*/ + /mob/living/carbon/can_use_hands() if(handcuffed) return 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f9c448df5e3..c63c03d8321 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -8,7 +8,7 @@ //why are these here and not in human_defines.dm //var/list/hud_list[10] var/datum/species/species //Contains icon generation and language information, set during New(). - var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. + var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. /mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0) @@ -482,8 +482,8 @@ if(3 to 4) stunprob = 30 if(5 to 6) stunprob = 40 if(7 to 8) stunprob = 60 - if(9) stunprob = 70 - if(10) stunprob = 95 + if(9) stunprob = 70 + if(10) stunprob = 95 if(prob(stunprob)) M.powerlevel -= 3 @@ -944,7 +944,7 @@ for(var/datum/data/record/R in data_core.security) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"security")) - var/t1 = sanitize(copytext(input("Add Comment:", "Sec. records", null, null) as message,1,MAX_MESSAGE_LEN)) + var/t1 = sanitize(copytext(input("Add Comment:", "Sec. records", null, null) as message,1,MAX_MESSAGE_LEN)) if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) ) return var/counter = 1 @@ -1075,7 +1075,7 @@ for(var/datum/data/record/R in data_core.medical) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"medical")) - var/t1 = sanitize(copytext(input("Add Comment:", "Med. records", null, null) as message,1,MAX_MESSAGE_LEN)) + var/t1 = sanitize(copytext(input("Add Comment:", "Med. records", null, null) as message,1,MAX_MESSAGE_LEN)) if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) ) return var/counter = 1 @@ -1285,8 +1285,8 @@ var/limb_path = organ_data["path"] var/obj/item/organ/external/O = new limb_path(temp_holder) if(H.get_limb_by_name(O.name)) //Check to see if the user already has an limb with the same name as the 'missing limb'. If they do, skip regrowth. - continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since, - //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name. + continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since, + //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name. else O = new limb_path(H) //Create the limb on the player. O.owner = H @@ -1704,7 +1704,7 @@ if((head_organ.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. hair += i - var/new_style = input(src, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair + var/new_style = input(src, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair if(incapacitated()) to_chat(src, "You were interrupted while changing your monitor display.") return @@ -1909,7 +1909,7 @@ if(current_size >= STAGE_THREE) var/list/handlist = list(l_hand, r_hand) for(var/obj/item/hand in handlist) - if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand)) + if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand)) step_towards(hand, src) to_chat(src, "\The [S] pulls \the [hand] from your grip!") apply_effect(current_size * 3, IRRADIATE) @@ -2031,3 +2031,103 @@ return 0 return . + +/mob/living/carbon/human/serialize() + // Currently: Limbs/organs only + var/list/data = ..() + var/list/limbs_list = list() + var/list/organs_list = list() + var/list/equip_list = list() + data["limbs"] = limbs_list + data["iorgans"] = organs_list + data["equip"] = equip_list + + data["dna"] = dna.serialize() + data["age"] = age + + // No being naked + data["ushirt"] = undershirt + data["socks"] = socks + data["uwear"] = underwear + + // Limbs + for(var/limb in organs_by_name) + var/obj/item/organ/O = organs_by_name[limb] + if(!O) + limbs_list[limb] = "missing" + continue + + limbs_list[limb] = O.serialize() + + // Internal organs/augments + for(var/organ in internal_organs) + var/obj/item/organ/O = organ + organs_list[O.name] = O.serialize() + + // Equipment + equip_list.len = slots_amt + for(var/i = 1, i < slots_amt, i++) + var/obj/item/thing = get_item_by_slot(i) + if(thing != null) + equip_list[i] = thing.serialize() + + return data + +/mob/living/carbon/human/deserialize(list/data) + var/list/limbs_list = data["limbs"] + var/list/organs_list = data["iorgans"] + var/list/equip_list = data["equip"] + var/turf/T = get_turf(src) + if(!islist(data["limbs"])) + throw EXCEPTION("Expected a limbs list, but found none") + + if(islist(data["dna"])) + dna.deserialize(data["dna"]) + real_name = dna.real_name + name = real_name + UpdateAppearance() + set_species(dna.species) + age = data["age"] + undershirt = data["ushirt"] + underwear = data["uwear"] + socks = data["socks"] + for(var/obj/item/organ/internal/iorgan in internal_organs) + qdel(iorgan) + + for(var/obj/item/organ/external/organ in organs) + qdel(organ) + + for(var/limb in limbs_list) + // Missing means skip this part - it's missing + if(limbs_list[limb] == "missing") + continue + // "New" code handles insertion and DNA sync'ing + var/obj/item/organ/external/E = list_to_object(limbs_list[limb], src) + E.sync_colour_to_dna() + + for(var/organ in organs_list) + // As above, "New" code handles insertion, DNA sync + list_to_object(organs_list[organ], src) + + + // De-serialize equipment + // #1: Jumpsuit + // #2: Outer suit + // #3+: Everything else + if(islist(equip_list[slot_w_uniform])) + var/obj/item/clothing/C = list_to_object(equip_list[slot_w_uniform], T) + equip_to_slot_if_possible(C, slot_w_uniform) + + if(islist(equip_list[slot_wear_suit])) + var/obj/item/clothing/C = list_to_object(equip_list[slot_wear_suit], T) + equip_to_slot_if_possible(C, slot_wear_suit) + + for(var/i = 1, i < slots_amt, i++) + if(i == slot_w_uniform || i == slot_wear_suit) + continue + if(islist(equip_list[i])) + var/obj/item/clothing/C = list_to_object(equip_list[i], T) + equip_to_slot_if_possible(C, i) + update_icons() + + ..() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index d39aa319e51..81fe04bc9de 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -110,11 +110,8 @@ if(I_HARM) //Vampire code if(M.mind && M.mind.vampire && (M.mind in ticker.mode.vampires) && !M.mind.vampire.draining && M.zone_sel && M.zone_sel.selecting == "head" && src != M) - if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(M, "Remove their mask!") - return - if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(M, "Remove your mask!") + if(species && species.flags & NO_BLOOD)//why this hell were we never checkinf for this? + to_chat(M, "They have no blood!") return if(mind && mind.vampire && (mind in ticker.mode.vampires)) to_chat(M, "Your fangs fail to pierce [src.name]'s cold flesh") diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index aa0724c5c80..f8d612aadba 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -2,7 +2,7 @@ var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) if(eyes) eyes.update_colour() - regenerate_icons() + update_body() /mob/living/carbon/human/var/list/organs = list() /mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b2b71d60545..1800adb31a8 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -487,14 +487,15 @@ return if(RESIST_HEAT in mutations) return - var/thermal_protection = get_thermal_protection() + if(on_fire) + var/thermal_protection = get_thermal_protection() - if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) - return - if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT) - bodytemperature += 11 - else - bodytemperature += BODYTEMP_HEATING_MAX + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + return + if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT) + bodytemperature += 11 + else + bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12)) /mob/living/carbon/human/proc/get_thermal_protection() var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 617d63c798b..bdb64ba0a98 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -614,6 +614,8 @@ H.clear_alert("high") /datum/species/proc/handle_hud_icons(mob/living/carbon/human/H) + if(!H.client) + return if(H.healths) if(H.stat == DEAD) H.healths.icon_state = "health7" @@ -633,11 +635,15 @@ else H.healths.icon_state = "health6" if(H.healthdoll) - H.healthdoll.overlays.Cut() if(H.stat == DEAD) H.healthdoll.icon_state = "healthdoll_DEAD" + if(H.healthdoll.overlays.len) + H.healthdoll.overlays.Cut() else - H.healthdoll.icon_state = "healthdoll_OVERLAY" + var/list/new_overlays = list() + var/list/cached_overlays = H.healthdoll.cached_healthdoll_overlays + // Use the dead health doll as the base, since we have proper "healthy" overlays now + H.healthdoll.icon_state = "healthdoll_DEAD" for(var/obj/item/organ/external/O in H.organs) var/damage = O.burn_dam + O.brute_dam var/comparison = (O.max_damage/5) @@ -652,8 +658,10 @@ icon_num = 4 if(damage > (comparison*4)) icon_num = 5 - if(icon_num) - H.healthdoll.overlays += image('icons/mob/screen_gen.dmi',"[O.limb_name][icon_num]") + new_overlays += "[O.limb_name][icon_num]" + H.healthdoll.overlays += (new_overlays - cached_overlays) + H.healthdoll.overlays -= (cached_overlays - new_overlays) + H.healthdoll.cached_healthdoll_overlays = new_overlays switch(H.nutrition) if(NUTRITION_LEVEL_FULL to INFINITY) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 50270ed3f78..b919912a6c1 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -107,17 +107,7 @@ Please contact me on #coderbus IRC. ~Carn x var/list/overlays_standing[TOTAL_LAYERS] var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed var/icon/skeleton - - -/mob/living/carbon/human/proc/apply_overlay(cache_index) - var/image/I = overlays_standing[cache_index] - if(I) - overlays += I - -/mob/living/carbon/human/proc/remove_overlay(cache_index) - if(overlays_standing[cache_index]) - overlays -= overlays_standing[cache_index] - overlays_standing[cache_index] = null + var/list/cached_standing_overlays = list() // List of everything currently in a human's actual overlays //UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING //this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers @@ -125,6 +115,7 @@ Please contact me on #coderbus IRC. ~Carn x /mob/living/carbon/human/update_icons() var/stealth = 0 var/obj/item/clothing/suit/armor/abductor/vest/V // Begin the most snowflakey bullshit code I've ever written. I'm so sorry, but there was no other way. + for(V in list(wear_suit)) if(V.stealth_active) stealth = 1 @@ -133,6 +124,7 @@ Please contact me on #coderbus IRC. ~Carn x if(stealth) icon = V.disguise.icon //if the suit is active, reference the suit's current loaded icon and overlays; this does not include hand overlays overlays.Cut() + cached_standing_overlays.Cut() // Make sure the cache gets rebuilt once the disguise is gone for(var/thing in V.disguise.overlays) if(thing) @@ -146,10 +138,28 @@ Please contact me on #coderbus IRC. ~Carn x overlays += I else icon = stand_icon - overlays.Cut() + var/list/new_overlays = list() + var/list/old_overlays = cached_standing_overlays - for(var/thing in overlays_standing) - if(thing) overlays += thing + // Totally regenerate if something touched our overlays + if(overlays.len != old_overlays.len) + overlays.Cut() + old_overlays.Cut() + + for(var/i in 1 to TOTAL_LAYERS) + var/image/I = overlays_standing[i] + if(I) + if(istype(I)) + // Since we avoid full overlay rebuilds, we have to reorganize the layers manually + I.layer = (-2 - (TOTAL_LAYERS - i)) // Highest layer gets -2, each prior layer is 1 lower + new_overlays += I + + if(frozen) // Admin freeze overlay + new_overlays += frozen + + overlays += (new_overlays - old_overlays) + overlays -= (old_overlays - new_overlays) + cached_standing_overlays = new_overlays update_transform() @@ -538,12 +548,13 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_fire() - remove_overlay(FIRE_LAYER) if(on_fire) - overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite, "layer"=-FIRE_LAYER) + if(!overlays_standing[FIRE_LAYER]) + overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite) + update_icons() else overlays_standing[FIRE_LAYER] = null - apply_overlay(FIRE_LAYER) + update_icons() /* --------------------------------------- */ //For legacy support. @@ -574,11 +585,12 @@ var/global/list/damage_icon_parts = list() update_inv_legcuffed(0) update_inv_pockets(0) update_inv_wear_pda(0) - UpdateDamageIcon() - update_icons() - update_fire() + UpdateDamageIcon(0) force_update_limbs() update_tail_layer(0) + overlays.Cut() // Force all overlays to regenerate + update_fire() + update_icons() /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 69a32f2c285..60c26dc4a50 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -18,6 +18,7 @@ var/turf/T = get_turf(src) if(!T) return 0 + // TODO: Tie into space manager if(T.z == ZLEVEL_CENTCOMM) //dont detect mobs on centcomm return 0 if(T.z >= MAX_Z) @@ -91,22 +92,6 @@ /mob/living/proc/calculate_affecting_pressure(var/pressure) return 0 - -//sort of a legacy burn method for /electrocute, /shock, and the e_chair -/mob/living/proc/burn_skin(burn_amount) - if(istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part - var/divided_damage = (burn_amount)/(H.organs.len) - var/extradam = 0 //added to when organ is at max dam - for(var/obj/item/organ/external/affecting in H.organs) - if(!affecting) continue - if(affecting.take_damage(0, divided_damage+extradam)) //TODO: fix the extradam stuff. Or, ebtter yet...rewrite this entire proc ~Carn - H.UpdateDamageIcon() - H.updatehealth() - return 1 - else if(istype(src, /mob/living/silicon/ai)) - return 0 - /mob/living/proc/adjustBodyTemp(actual, desired, incrementboost) var/temperature = actual var/difference = abs(actual-desired) //get difference diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 2049d5fd21d..50576bcecad 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -151,9 +151,13 @@ /mob/living/proc/IgniteMob() if(fire_stacks > 0 && !on_fire) on_fire = 1 + visible_message("[src] catches fire!", \ + "You're set on fire!") set_light(light_range + 3,l_color = "#ED9200") throw_alert("fire", /obj/screen/alert/fire) update_fire() + return 1 + return 0 /mob/living/proc/ExtinguishMob() if(on_fire) @@ -167,14 +171,20 @@ return /mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) + fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) + if(on_fire && fire_stacks <= 0) + ExtinguishMob() /mob/living/proc/handle_fire() - if(fire_stacks < 0) - fire_stacks++ //If we've doused ourselves in water to avoid fire, dry off slowly - fire_stacks = min(0, fire_stacks)//So we dry ourselves back to default, nonflammable. + if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly + fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable. if(!on_fire) return 1 + if(fire_stacks > 0) + adjust_fire_stacks(-0.1) //the fire is slowly consumed + else + ExtinguishMob() + return var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment if(G.oxygen < 1) ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire @@ -183,7 +193,7 @@ location.hotspot_expose(700, 50, 1) /mob/living/fire_act() - adjust_fire_stacks(0.5) + adjust_fire_stacks(3) IgniteMob() //Mobs on Fire end diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 842b03c4bbd..9d64f278b4a 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -62,7 +62,6 @@ var/list/ai_verbs_default = list( var/datum/module_picker/malf_picker var/processing_time = 100 var/list/datum/AI_Module/current_modules = list() - var/fire_res_on_core = 0 var/can_dominate_mechs = 0 var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite @@ -640,13 +639,14 @@ var/list/ai_verbs_default = list( if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) return - var/ai_allowed_Zlevel = list(1,3,5) + var/ai_allowed_Zlevel = list(ZLEVEL_STATION,ZLEVEL_TELECOMMS,ZLEVEL_ASTEROID) var/d var/area/bot_area d += "Query network status
    " d += "" for(var/mob/living/simple_animal/bot/Bot in simple_animal_list) + // TODO: Tie into space manager if((Bot.z in ai_allowed_Zlevel) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected! bot_area = get_area(Bot) d += "" @@ -811,49 +811,118 @@ var/list/ai_verbs_default = list( custom_hologram = 1 // option is given in hologram menu var/input - if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member") + switch(alert("Would you like to select a hologram based on a crew member, an animal, or switch to a unique avatar?",,"Crew Member","Unique","Animal")) + if("Crew Member") + var/personnel_list[] = list() - var/personnel_list[] = list() + for(var/datum/data/record/t in data_core.locked)//Look in data core locked. + personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image. - for(var/datum/data/record/t in data_core.locked)//Look in data core locked. - personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image. + if(personnel_list.len) + input = input("Select a crew member:") as null|anything in personnel_list + var/icon/character_icon = personnel_list[input] + if(character_icon) + qdel(holo_icon)//Clear old icon so we're not storing it in memory. + holo_icon = getHologramIcon(icon(character_icon)) + else + alert("No suitable records found. Aborting.") + + if("Animal") + var/icon_list[] = list( + "Bear", + "Carp", + "Chicken", + "Corgi", + "Cow", + "Crab", + "Deer", + "Fox", + "Goat", + "Goose", + "Kitten", + "Kitten2", + "Pig", + "Poly", + "Pug", + "Seal", + "Spider", + "Turkey" + ) + + input = input("Please select a hologram:") as null|anything in icon_list + if(input) + qdel(holo_icon) + switch(input) + if("Bear") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"bear")) + if("Carp") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"carp")) + if("Chicken") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"chicken_brown")) + if("Corgi") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"corgi")) + if("Cow") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"cow")) + if("Crab") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"crab")) + if("Deer") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"deer")) + if("Fox") + holo_icon = getHologramIcon(icon('icons/mob/pets.dmi',"fox")) + if("Goat") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"goat")) + if("Goose") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"goose")) + if("Kitten") + holo_icon = getHologramIcon(icon('icons/mob/pets.dmi',"cat")) + if("Kitten2") + holo_icon = getHologramIcon(icon('icons/mob/pets.dmi',"cat2")) + if("Pig") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"pig")) + if("Poly") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"parrot_fly")) + if("Pug") + holo_icon = getHologramIcon(icon('icons/mob/pets.dmi',"pug")) + if("Seal") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"seal")) + if("Spider") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"guard")) + if("Turkey") + holo_icon = getHologramIcon(icon('icons/mob/animal.dmi',"turkey")) - if(personnel_list.len) - input = input("Select a crew member:") as null|anything in personnel_list - var/icon/character_icon = personnel_list[input] - if(character_icon) - qdel(holo_icon)//Clear old icon so we're not storing it in memory. - holo_icon = getHologramIcon(icon(character_icon)) else - alert("No suitable records found. Aborting.") + var/icon_list[] = list( + "default", + "floating face", + "xeno queen", + "eldritch", + "ancient machine" + ) + if(custom_hologram) //insert custom hologram + icon_list.Add("custom") - else - var/icon_list[] = list( - "default", - "floating face", - "xeno queen", - "eldritch", - "ancient machine" - ) - if(custom_hologram) //insert custom hologram - icon_list.Add("custom") + input = input("Please select a hologram:") as null|anything in icon_list + if(input) + qdel(holo_icon) + switch(input) + if("default") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) + if("floating face") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) + if("xeno queen") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) + if("eldritch") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) + if("ancient machine") + holo_icon = getHologramIcon(icon('icons/mob/ancient_machine.dmi', "ancient_machine")) + if("custom") + if("[ckey]-ai-holo" in icon_states('icons/mob/custom-synthetic.dmi')) + holo_icon = getHologramIcon(icon('icons/mob/custom-synthetic.dmi', "[ckey]-ai-holo")) + else if("[ckey]-ai-holo" in icon_states('icons/mob/custom-synthetic64.dmi')) + holo_icon = getHologramIcon(icon('icons/mob/custom-synthetic64.dmi', "[ckey]-ai-holo")) + else + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) - input = input("Please select a hologram:") as null|anything in icon_list - if(input) - qdel(holo_icon) - switch(input) - if("default") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) - if("floating face") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) - if("xeno queen") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) - if("eldritch") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) - if("ancient machine") - holo_icon = getHologramIcon(icon('icons/mob/ancient_machine.dmi', "ancient_machine")) - if("custom") - holo_icon = getHologramIcon(icon('icons/mob/custom-synthetic.dmi', "[ckey]-ai-holo")) return /mob/living/silicon/ai/proc/corereturn() @@ -1066,3 +1135,18 @@ var/list/ai_verbs_default = list( eyeobj.setLoc(get_turf(C)) client.eye = eyeobj return 1 + +/mob/living/silicon/ai/proc/relay_speech(mob/living/M, text, verb, datum/language/speaking) + if(!say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. + if(speaking) + text = speaking.scramble(text) + else + text = stars(text) + var/name_used = M.GetVoice() + //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. + var/rendered + if(speaking) + rendered = "Relayed Speech: [name_used] [speaking.format_message(text, verb)]" + else + rendered = "Relayed Speech: [name_used] [verb], \"[text]\"" + show_message(rendered, 2) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 00435fdd17a..71a2e6cba36 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -116,3 +116,7 @@ return //won't work if dead acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") + +/mob/camera/aiEye/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) + if(relay_speech) + ai.relay_speech(speaker, message, verb, language) diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm index 585c484a73a..0859acc1cb2 100644 --- a/code/modules/mob/living/silicon/ai/latejoin.dm +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -34,7 +34,7 @@ var/global/list/empty_playable_ai_cores = list() job_master.FreeRole(job) if(mind.objectives.len) - qdel(mind.objectives) + mind.objectives.Cut() mind.special_role = null else if(ticker.mode.name == "AutoTraitor") diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index f82db9b4662..6599c31c5ce 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -152,10 +152,7 @@ health = 100 stat = CONSCIOUS else - if(fire_res_on_core) - health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss() - else - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() diag_hud_set_status() diag_hud_set_health() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 3cf863a3591..5f38114a518 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -566,6 +566,9 @@ var/obj/item/weapon/holder/H = ..() if(!istype(H)) return + if(resting) + icon_state = "[chassis]" + resting = 0 H.icon_state = "pai-[icon_state]" H.item_state = "pai-[icon_state]" grabber.put_in_active_hand(H)//for some reason unless i call this it dosen't work diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 3e15e7118d9..6d4c3a45150 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -499,6 +499,7 @@ /mob/living/silicon/pai/proc/hackloop() var/turf/T = get_turf_or_move(src.loc) for(var/mob/living/silicon/ai/AI in player_list) + // TODO: Tie into space manager if(!T || !(T.z in config.contact_levels)) break if(T.loc) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm index 3a316b0140b..aeed17ef9fd 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm @@ -113,7 +113,7 @@ if(istype(src,/mob/dead/observer)) var/mob/dead/observer/G = src if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted) - to_chat(usr, "\blue Upon using the antagHUD you forfeited the ability to join the round.") + to_chat(usr, "Upon using the antagHUD you forfeited the ability to join the round.") return if(G.started_as_observer == 1) joinedasobserver = 1 @@ -133,6 +133,9 @@ to_chat(usr, "You must wait 10 minutes to respawn as a drone!") return + if(alert("Are you sure you want to respawn as a drone?", "Are you sure?", "Yes", "No") != "Yes") + return + for(var/obj/machinery/drone_fabricator/DF in world) if(DF.stat & NOPOWER || !DF.produce_drones) continue diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index b7f3eec50bc..8cb7fde6ffc 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -669,9 +669,6 @@ var/list/robot_verbs_default = list( C.r_arm = new/obj/item/robot_parts/r_arm(C) C.updateicon() new/obj/item/robot_parts/chest(loc) - // This doesn't work. Don't use it. - //src.Destroy() - // del() because it's infrequent and mobs act weird in qdel. qdel(src) else // Okay we're not removing the cell or an MMI, but maybe something else? diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 5f078682947..8fa770d371b 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -6,7 +6,7 @@ icon_state = "corgi" icon_living = "corgi" icon_dead = "corgi_dead" - gender = MALE + gender = NEUTER health = 30 maxHealth = 30 speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") @@ -33,6 +33,8 @@ ..() default_atmos_requirements = src.atmos_requirements regenerate_icons() + if(gender == NEUTER) + gender = pick(MALE, FEMALE) /mob/living/simple_animal/pet/corgi/Life() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index a770f6b1c32..b6cda2e0e3c 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -53,6 +53,7 @@ return var/mob/living/simple_animal/hostile/illusion/M = new(loc) M.faction = faction.Copy() + M.attack_sound = attack_sound M.Copy_Parent(parent_mob, 80, health/2, melee_damage_upper, multiply_chance/2) M.GiveTarget(L) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index c0616bc5eea..ac9b8562681 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -127,11 +127,12 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca /mob/living/simple_animal/hostile/mimic/copy/Life() ..() + if(!target && !ckey) //Objects eventually revert to normal if no one is around to terrorize + adjustBruteLoss(1) for(var/mob/living/M in contents) //a fix for animated statues from the flesh to stone spell death() /mob/living/simple_animal/hostile/mimic/copy/death(gibbed) - for(var/atom/movable/M in src) M.loc = get_turf(src) ..() @@ -186,7 +187,6 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca if(destroy_original) qdel(O) return 1 - return /mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings() if(destroy_objects) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index d2dbd5f14f2..816ec1979a9 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -407,26 +407,7 @@ return /mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/living/user as mob) //Marker -Agouri - if(istype(O, /obj/item/stack/medical) && healable) - if(stat != DEAD) - var/obj/item/stack/medical/MED = O - if(health < maxHealth) - if(MED.amount >= 1) - if(MED.heal_brute >= 1) - heal_organ_damage((MED.heal_brute * 1.66), (MED.heal_burn * 1.66)) - MED.use(1) - visible_message("[user] applies [MED] on [src]") - return - else - to_chat(user, "[MED] won't help at all.") - return - else - to_chat(user, "[src] is at full health.") - return - else - to_chat(user, "[src] is dead, medical items won't bring it back to life.") - return - else if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) + if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) var/obj/item/clothing/accessory/petcollar/C = O user.drop_item() C.forceMove(src) @@ -560,16 +541,24 @@ return 0 return 1 +/mob/living/simple_animal/handle_fire() + return + +/mob/living/simple_animal/update_fire() + return + +/mob/living/simple_animal/IgniteMob() + return 0 + +/mob/living/simple_animal/ExtinguishMob() + return + /mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE) if(damage <= force_threshold || !damage_coeff[damagetype]) visible_message("[src] looks unharmed from the damage.") else apply_damage(damage, damagetype) - -/mob/living/simple_animal/update_fire() - return - /mob/living/simple_animal/update_transform() var/matrix/ntransform = matrix(transform) //aka transform.Copy() var/changed = 0 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 37bb39b7754..e4765b4f106 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -22,7 +22,7 @@ */ var/obj/screen/zone_sel/zone_sel = null var/obj/screen/leap_icon = null - var/obj/screen/healthdoll = null + var/obj/screen/healthdoll/healthdoll = null var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot var/damageoverlaytemp = 0 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 383f75b757f..682abdb383d 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -402,7 +402,7 @@ global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") /mob/new_player/proc/LateChoices() - var/mills = world.time // 1/10 of a second, not real milliseconds but whatever + var/mills = ROUND_TIME // 1/10 of a second, not real milliseconds but whatever //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something var/mins = (mills % 36000) / 600 var/hours = mills / 36000 diff --git a/code/modules/nano/interaction/base.dm b/code/modules/nano/interaction/base.dm index 0db9eb19eeb..113c9e2878b 100644 --- a/code/modules/nano/interaction/base.dm +++ b/code/modules/nano/interaction/base.dm @@ -12,9 +12,9 @@ return STATUS_CLOSE /mob/proc/shared_nano_interaction() - if(src.stat || !client) + if(stat || !client) return STATUS_CLOSE // no updates, close the interface - else if(restrained() || lying || stat || stunned || weakened) + else if(restrained() || lying || stunned || weakened) return STATUS_UPDATE // update only (orange visibility) return STATUS_INTERACTIVE diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index a97c693ec94..50c2bd79143 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -41,6 +41,7 @@ // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) // unless it's on the same level as the object it's interacting with. var/turf/T = get_turf(src_object) + // TODO: Tie into space manager if(!T || !(z == T.z || (T.z in config.player_levels))) return STATUS_CLOSE @@ -102,4 +103,4 @@ . = shared_nano_interaction(src_object) if(. != STATUS_CLOSE) if(!(src_object in contents)) - . = STATUS_CLOSE \ No newline at end of file + . = STATUS_CLOSE diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm index a587295b582..65f5a9299ee 100644 --- a/code/modules/nano/modules/crew_monitor.dm +++ b/code/modules/nano/modules/crew_monitor.dm @@ -2,9 +2,10 @@ name = "Crew monitor" /datum/nano_module/crew_monitor/Topic(href, href_list) - if(..()) + if(..()) return 1 var/turf/T = get_turf(nano_host()) + // TODO: Tie into space manager if(!T || !(T.z in config.player_levels)) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") return 0 @@ -38,4 +39,3 @@ // should make the UI auto-update; doesn't seem to? ui.set_auto_update(1) - \ No newline at end of file diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index e8db4c58110..513233912f2 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -10,6 +10,7 @@ var/obj/item/weapon/pen/haspen //The stored pen. var/obj/item/weapon/toppaper //The topmost piece of paper. slot_flags = SLOT_BELT + burn_state = FLAMMABLE /obj/item/weapon/clipboard/New() update_icon() diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index 12f9e13a4e9..0dcff2dcee2 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -5,6 +5,7 @@ icon_state = "folder" w_class = 2 pressure_resistance = 2 + burn_state = FLAMMABLE /obj/item/weapon/folder/blue desc = "A blue folder." @@ -39,7 +40,7 @@ if(!n_name) return n_name = sanitize(copytext(n_name, 1, MAX_NAME_LEN)) - + if((loc == usr || Adjacent(usr)) && usr.stat == 0) name = "folder[(n_name ? text("- '[n_name]'") : null)]" return diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index a3ec39243a9..492ea726739 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -16,6 +16,8 @@ pressure_resistance = 0 slot_flags = SLOT_HEAD body_parts_covered = HEAD + burn_state = FLAMMABLE + burntime = 5 attack_verb = list("bapped") var/info //What's actually written on the paper. @@ -289,30 +291,6 @@ \[hr\] : Adds a horizontal rule. "}, "window=paper_help") -/obj/item/weapon/paper/proc/burnpaper(obj/item/weapon/lighter/P, mob/user) - var/class = "" - - if(P.lit && !user.restrained()) - if(istype(P, /obj/item/weapon/lighter/zippo)) - class = "" - - user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like \he's trying to burn it!", \ - "[class]You hold \the [P] up to \the [src], burning it slowly.") - - spawn(20) - if(get_dist(src, user) < 2 && user.get_active_hand() == P && P.lit) - user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ - "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") - - if(user.get_inactive_hand() == src) - user.unEquip(src) - - new /obj/effect/decal/cleanable/ash(get_turf(src)) - qdel(src) - - else - to_chat(user, "\red You must hold \the [P] steady to burn \the [src].") - /obj/item/weapon/paper/Topic(href, href_list) ..() if(!usr || (usr.stat || usr.restrained())) @@ -361,8 +339,12 @@ update_icon() -/obj/item/weapon/paper/attackby(obj/item/weapon/P as obj, mob/user as mob, params) +/obj/item/weapon/paper/attackby(obj/item/weapon/P, mob/living/user, params) ..() + + if(burn_state == ON_FIRE) + return + var/clown = 0 if(user.mind && (user.mind.assigned_role == "Clown")) clown = 1 @@ -443,11 +425,27 @@ to_chat(user, "You stamp the paper with your rubber stamp.") - else if(istype(P, /obj/item/weapon/lighter)) - burnpaper(P, user) + if(is_hot(P)) + if((CLUMSY in user.mutations) && prob(10)) + user.visible_message("[user] accidentally ignites themselves!", \ + "You miss the paper and accidentally light yourself on fire!") + user.unEquip(P) + user.adjust_fire_stacks(1) + user.IgniteMob() + return + + if(!Adjacent(user)) //to prevent issues as a result of telepathically lighting a paper + return + + user.unEquip(src) + user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!") + fire_act() add_fingerprint(user) - return + +/obj/item/weapon/paper/fire_act() + ..() + info = "[stars(info)]" /obj/item/weapon/paper/proc/stamp(var/obj/item/weapon/stamp/S) stamps += (!stamps || stamps == "" ? "
    " : "") + "" diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 2c5c154bca8..9770fb8c523 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -8,23 +8,27 @@ throw_speed = 3 throw_range = 7 pressure_resistance = 8 + burn_state = FLAMMABLE var/amount = 30 //How much paper is in the bin. - var/list/papers = new/list() //List of papers put in the bin for reference. -/* - autoignition_temperature = 519.15 // Kelvin + var/list/papers = list() //List of papers put in the bin for reference. + +/obj/item/weapon/paper_bin/fire_act() + if(!amount) + return + ..() + +/obj/item/weapon/paper_bin/Destroy() + if(papers) + for(var/i in papers) + qdel(i) + papers.Cut() + return ..() + +/obj/item/weapon/paper_bin/burn() + amount = 0 + extinguish() + update_icon() -/obj/item/weapon/paper_bin/ignite(var/temperature) - on_fire=1 - visible_message("\The [src]'s paper bursts into flame!") - overlays += fire_sprite - spawn(rand(3,10) SECONDS) - if(!on_fire) - return - new ashtype(src.loc) - papers=0 - amount=0 - update_icon() -*///LINDA shit figure out later /obj/item/weapon/paper_bin/MouseDrop(atom/over_object) var/mob/M = usr if(M.restrained() || M.stat || !Adjacent(M)) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index a09589f22ee..364f7b50f02 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -16,6 +16,7 @@ icon_state = "film" item_state = "electropack" w_class = 1 + burn_state = FLAMMABLE /******** @@ -27,6 +28,8 @@ icon_state = "photo" item_state = "paper" w_class = 2 + burn_state = FLAMMABLE + burntime = 5 var/icon/img //Big photo image var/scribble //Scribble on the back. var/icon/tiny @@ -106,7 +109,8 @@ icon = 'icons/obj/items.dmi' icon_state = "album" item_state = "briefcase" - can_hold = list("/obj/item/weapon/photo",) + can_hold = list("/obj/item/weapon/photo") + burn_state = FLAMMABLE /obj/item/weapon/storage/photo_album/MouseDrop(obj/over_object as obj) diff --git a/code/modules/pda/cart_apps.dm b/code/modules/pda/cart_apps.dm index 55acf9b70eb..1c407bd223c 100644 --- a/code/modules/pda/cart_apps.dm +++ b/code/modules/pda/cart_apps.dm @@ -316,6 +316,7 @@ if(shuttle_master.supply.mode == SHUTTLE_CALL) supplyData["shuttle_moving"] = 1 + // TODO: Tie into space manager if(shuttle_master.supply.z != ZLEVEL_STATION) supplyData["shuttle_loc"] = "station" else @@ -418,4 +419,4 @@ JaniData["buckets"] = BucketData JaniData["cleanbots"] = CbotData JaniData["carts"] = CartData - data["janitor"] = JaniData \ No newline at end of file + data["janitor"] = JaniData diff --git a/code/modules/pda/messenger.dm b/code/modules/pda/messenger.dm index 88d6024ba1b..2a8ca83b218 100644 --- a/code/modules/pda/messenger.dm +++ b/code/modules/pda/messenger.dm @@ -158,6 +158,7 @@ if(signal.data["done"]) useTC = 1 var/turf/pos = get_turf(P) + // TODO: Tie into space manager if(pos.z in signal.data["level"]) useTC = 2 //Let's make this barely readable @@ -211,4 +212,4 @@ return plist /datum/data/pda/app/messenger/proc/can_receive() - return pda.owner && !toff && !hidden \ No newline at end of file + return pda.owner && !toff && !hidden diff --git a/code/modules/persistence/persistence.dm b/code/modules/persistence/persistence.dm new file mode 100644 index 00000000000..4c1b40eaa98 --- /dev/null +++ b/code/modules/persistence/persistence.dm @@ -0,0 +1,75 @@ +/* +* Returns a byond list that can be passed to the "deserialize" proc +* to bring a new instance of this atom to its original state +* +* If we want to store this info, we can pass it to `json_encode` or some other +* interface that suits our fancy, to make it into an easily-handled string +*/ +/datum/proc/serialize() + var/data = list("type" = "[type]") + return data + +/* +* This is given the byond list from above, to bring this atom to the state +* described in the list. +* This will be called after `New` but before `initialize`, so linking and stuff +* would probably be handled in `initialize` +* +* Also, this should only be called by `json_to_object` in persistence.dm - at least +* with current plans - that way it can actually initialize the type from the list +*/ +/datum/proc/deserialize(var/list/data) + return + +/atom + // This var isn't actually used for anything, but is present so that + // DM's map reader doesn't forfeit on reading a JSON-serialized map + var/map_json_data + +// This is so specific atoms can override these, and ignore certain ones +/atom/proc/vars_to_save() + return list("color","dir","icon","icon_state","name","pixel_x","pixel_y") + +/atom/proc/map_important_vars() + // A list of important things to save in the map editor + return list("color","dir","icon","icon_state","layer","name","pixel_x","pixel_y") + +/area/map_important_vars() + // Keep the area default icons, to keep things nice and legible + return list("name") + +// No need to save any state of an area by default +/area/vars_to_save() + return list("name") + +/atom/serialize() + var/list/data = ..() + for(var/thing in vars_to_save()) + if(vars[thing] != initial(vars[thing])) + data[thing] = vars[thing] + return data + + +/atom/deserialize(var/list/data) + for(var/thing in vars_to_save()) + if(thing in data) + vars[thing] = data[thing] + ..() + + +/proc/json_to_object(var/json_data, var/loc) + var/data = json_decode(json_data) + return list_to_object(data, loc) + +/proc/list_to_object(var/list/data, var/loc) + if(!islist(data)) + throw EXCEPTION("You didn't give me a list, bucko") + if(!("type" in data)) + throw EXCEPTION("No 'type' field in the data") + var/path = text2path(data["type"]) + if(!path) + throw EXCEPTION("Path not found: [path]") + + var/atom/movable/thing = new path(loc) + thing.deserialize(data) + return thing diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 87ce338afd1..b6eb99eb958 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -170,6 +170,7 @@ apcs -= src if(malfai && operating) if(ticker.mode.config_tag == "malfunction") + // TODO: Tie into space manager if(src.z == ZLEVEL_STATION) ticker.mode:apcs-- area.power_light = 0 @@ -976,8 +977,8 @@ return 0 else if(href_list["overload"]) - if(istype(usr, /mob/living/silicon) && !aidisabled) - src.overload_lighting() + if(issilicon(usr) && !aidisabled) + overload_lighting() else if(href_list["malfhack"]) var/mob/living/silicon/ai/malfai = usr @@ -995,6 +996,7 @@ malfai.malfhacking = 0 locked = 1 if(ticker.mode.config_tag == "malfunction") + // TODO: Tie into space manager if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas)) ticker.mode:apcs++ if(usr:parent) @@ -1027,6 +1029,7 @@ if(malfai) if(ticker.mode.config_tag == "malfunction") + // TODO: Tie into space manager if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas)) operating ? ticker.mode:apcs++ : ticker.mode:apcs-- @@ -1042,6 +1045,7 @@ if(!malf.can_shunt) to_chat(malf, "You cannot shunt.") return + // TODO: Tie into space manager if(!(src.z in config.station_levels)) return src.occupier = new /mob/living/silicon/ai(src,malf.laws,null,1) @@ -1091,6 +1095,7 @@ /obj/machinery/power/apc/proc/ion_act() //intended to be exactly the same as an AI malf attack + // TODO: Tie into space manager if(!src.malfhack && (src.z in config.station_levels)) if(prob(3)) src.locked = 1 @@ -1366,6 +1371,7 @@ /obj/machinery/power/apc/proc/set_broken() if(malfai && operating) if(ticker.mode.config_tag == "malfunction") + // TODO: Tie into space manager if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas)) ticker.mode:apcs-- stat |= BROKEN @@ -1377,17 +1383,17 @@ // overload all the lights in this APC area -/obj/machinery/power/apc/proc/overload_lighting(var/chance = 100) - if(/* !get_connection() || */ !operating || shorted) +/obj/machinery/power/apc/proc/overload_lighting(chance = 100) + if(!operating || shorted) return - if( cell && cell.charge>=20) - cell.use(20); + if(cell && cell.charge >= 20) + cell.use(20) spawn(0) for(var/obj/machinery/light/L in area) if(prob(chance)) L.on = 1 L.broken() - sleep(1) + stoplag() /obj/machinery/power/apc/proc/setsubsystem(val) if(cell && cell.charge > 0) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 3bbfbb2248c..d2d2c619882 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -24,7 +24,7 @@ By design, d1 is the smallest direction and d2 is the highest /obj/structure/cable level = 1 - anchored =1 + anchored = 1 on_blueprints = TRUE var/datum/powernet/powernet name = "power cable" @@ -457,12 +457,13 @@ obj/structure/cable/proc/cableColor(var/colorC) #define MAXCOIL 30 -var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \ - new/datum/stack_recipe("cable restraints", /obj/item/weapon/restraints/handcuffs/cable, 15), \ - ) +var/global/list/datum/stack_recipe/cable_coil_recipes = list( + new /datum/stack_recipe/cable_restraints("cable restraints", /obj/item/weapon/restraints/handcuffs/cable, 15), +) /obj/item/stack/cable_coil name = "cable coil" + singular_name = "cable" icon = 'icons/obj/power.dmi' icon_state = "coil" item_state = "coil_red" diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 8833e047a7e..ea633c7e78f 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -124,6 +124,7 @@ var/const/GRAV_NEEDS_WRENCH = 3 O.main_part = null qdel(O) for(var/area/A in world) + // TODO: Tie into space manager if(!(A.z in config.station_levels)) continue A.gravitychange(0,A) shake_everyone() @@ -301,6 +302,7 @@ var/const/GRAV_NEEDS_WRENCH = 3 investigate_log("was brought online and is now producing gravity for this level.", "gravity") message_admins("The gravity generator was brought online. ([area.name])") for(var/area/A in world) + // TODO: Tie into space manager if(!(A.z in config.station_levels)) continue A.gravitychange(1,A) else @@ -309,6 +311,7 @@ var/const/GRAV_NEEDS_WRENCH = 3 investigate_log("was brought offline and there is now no gravity for this level.", "gravity") message_admins("The gravity generator was brought offline with no backup generator. ([area.name])") for(var/area/A in world) + // TODO: Tie into space manager if(!(A.z in config.station_levels)) continue A.gravitychange(0,A) @@ -377,6 +380,7 @@ var/const/GRAV_NEEDS_WRENCH = 3 shake_camera(M, 15, 1) M.playsound_local(our_turf, 'sound/effects/alert.ogg', 100, 1, 0.5) +// TODO: Tie into space manager /obj/machinery/gravity_generator/main/proc/gravity_in_level() var/turf/T = get_turf(src) if(!T) @@ -385,6 +389,7 @@ var/const/GRAV_NEEDS_WRENCH = 3 return length(gravity_generators["[T.z]"]) return 0 +// TODO: Tie into space manager /obj/machinery/gravity_generator/main/proc/update_list() var/turf/T = get_turf(src.loc) if(T) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index a96a4851c81..18a760f5f1d 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -514,8 +514,8 @@ status = LIGHT_EMPTY update() -/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0) - if(status == LIGHT_EMPTY) +/obj/machinery/light/proc/broken(skip_sound_and_sparks = 0) + if(status == LIGHT_EMPTY || status == LIGHT_BROKEN) return if(!skip_sound_and_sparks) @@ -715,4 +715,4 @@ var/obj/item/organ/external/limb = user.get_organ(oname) if(limb) limb.droplimb(0, DROPLIMB_BURN) - return FIRELOSS \ No newline at end of file + return FIRELOSS diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index e4704dff26a..751fda95fab 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -15,10 +15,8 @@ var/obj/machinery/field/generator/FG2 = null /obj/machinery/field/containment/Destroy() - if(FG1 && !FG1.clean_up) - FG1.cleanup() - if(FG2 && !FG2.clean_up) - FG2.cleanup() + FG1.fields -= src + FG2.fields -= src return ..() /obj/machinery/field/containment/attack_hand(mob/user) @@ -67,35 +65,26 @@ /obj/machinery/field var/hasShocked = 0 //Used to add a delay between shocks. In some cases this used to crash servers by spawning hundreds of sparks every second. -/obj/machinery/field/CanPass(mob/mover, turf/target, height=0) +/obj/machinery/field/CanPass(atom/movable/mover, turf/target, height=0) + if(hasShocked) + return 0 if(isliving(mover)) // Don't let mobs through shock_field(mover) return 0 - return ..() - -/obj/machinery/field/CanPass(obj/mover, turf/target, height=0) - if((istype(mover, /obj/machinery) && !istype(mover, /obj/singularity)) || \ - istype(mover, /obj/structure) || \ - istype(mover, /obj/mecha)) + if(istype(mover, /obj/machinery) || istype(mover, /obj/structure) || istype(mover, /obj/mecha)) bump_field(mover) return 0 return ..() /obj/machinery/field/proc/shock_field(mob/living/user) - if(hasShocked) - return 0 if(isliving(user)) - hasShocked = 1 var/shock_damage = min(rand(30,40),rand(30,40)) if(iscarbon(user)) var/stun = min(shock_damage, 15) user.Stun(stun) user.Weaken(10) - user.burn_skin(shock_damage) - user.visible_message("[user.name] was shocked by the [src.name]!", \ - "You feel a powerful shock course through your body, sending you flying!", \ - "You hear a heavy electrical crack.") + user.electrocute_act(shock_damage, src, 1) else if(issilicon(user)) if(prob(20)) @@ -108,13 +97,14 @@ user.updatehealth() bump_field(user) - spawn(5) - hasShocked = 0 - return - /obj/machinery/field/proc/bump_field(atom/movable/AM as mob|obj) + if(hasShocked) + return 0 + hasShocked = 1 var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread s.set_up(5, 1, AM.loc) s.start() var/atom/target = get_edge_target_turf(AM, get_dir(src, get_step_away(AM, src))) AM.throw_at(target, 200, 4) + spawn(5) + hasShocked = 0 diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index ed4d7bbc537..d55e240bdf6 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -13,6 +13,15 @@ field_generator power level display */ #define field_generator_max_power 250 + +#define FG_UNSECURED 0 +#define FG_SECURED 1 +#define FG_WELDED 2 + +#define FG_OFFLINE 0 +#define FG_CHARGING 1 +#define FG_ONLINE 2 + /obj/machinery/field/generator name = "Field Generator" desc = "A large thermal battery that projects a high amount of energy when powered." @@ -22,134 +31,109 @@ field_generator power level display density = 1 use_power = 0 var/const/num_power_levels = 6 // Total number of power level icon has - var/Varedit_start = 0 - var/Varpower = 0 - var/active = 0 + var/power_level = 0 + var/active = FG_OFFLINE var/power = 20 // Current amount of power - var/state = 0 + var/state = FG_UNSECURED var/warming_up = 0 var/list/obj/machinery/field/containment/fields var/list/obj/machinery/field/generator/connected_gens var/clean_up = 0 - /obj/machinery/field/generator/update_icon() overlays.Cut() if(warming_up) overlays += "+a[warming_up]" if(fields.len) overlays += "+on" - // Power level indicator - // Scale % power to % num_power_levels and truncate value - var/level = round(num_power_levels * power / field_generator_max_power) - // Clamp between 0 and num_power_levels for out of range power values - level = Clamp(level, 0, num_power_levels) - if(level) - overlays += "+p[level]" - - return + if(power_level) + overlays += "+p[power_level]" /obj/machinery/field/generator/New() ..() fields = list() connected_gens = list() - return /obj/machinery/field/generator/process() - if(Varedit_start == 1) - if(active == 0) - active = 1 - state = 2 - power = field_generator_max_power - anchored = 1 - warming_up = 3 - start_fields() - update_icon() - Varedit_start = 0 - - if(src.active == 2) + if(active == FG_ONLINE) calc_power() - update_icon() - return - /obj/machinery/field/generator/attack_hand(mob/user) - if(state == 2) + if(state == FG_WELDED) if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on - if(src.active >= 1) - to_chat(user, "You are unable to turn off the [src.name] once it is online!") + if(active >= FG_CHARGING) + to_chat(user, "You are unable to turn off the [name] once it is online!") return 1 else - user.visible_message("[user.name] turns on the [src.name].", \ - "You turn on the [src.name].", \ + user.visible_message("[user.name] turns on the [name].", \ + "You turn on the [name].", \ "You hear heavy droning.") turn_on() investigate_log("activated by [user.key].","singulo") - src.add_fingerprint(user) + add_fingerprint(user) else - to_chat(user, "The [src] needs to be firmly secured to the floor first!") - return + to_chat(user, "[src] needs to be firmly secured to the floor first!") /obj/machinery/field/generator/attackby(obj/item/W, mob/user, params) if(active) - to_chat(user, "The [src] needs to be off!") + to_chat(user, "[src] needs to be off!") return else if(istype(W, /obj/item/weapon/wrench)) switch(state) - if(0) + if(FG_UNSECURED) if(isinspace()) return - state = 1 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - user.visible_message("[user.name] secures [src.name] to the floor.", \ + state = FG_SECURED + playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) + user.visible_message("[user.name] secures [name] to the floor.", \ "You secure the external reinforcing bolts to the floor.", \ "You hear ratchet.") - src.anchored = 1 - if(1) - state = 0 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \ + anchored = 1 + if(FG_SECURED) + state = FG_UNSECURED + playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) + user.visible_message("[user.name] unsecures [name] reinforcing bolts from the floor.", \ "You undo the external reinforcing bolts.", \ "You hear ratchet.") - src.anchored = 0 - if(2) - to_chat(user, "The [src.name] needs to be unwelded from the floor!") - return + anchored = 0 + if(FG_WELDED) + to_chat(user, "The [name] needs to be unwelded from the floor!") + else if(istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W switch(state) - if(0) - to_chat(user, "The [src.name] needs to be wrenched to the floor!") - return - if(1) + if(FG_UNSECURED) + to_chat(user, "The [name] needs to be wrenched to the floor!") + + if(FG_SECURED) if(WT.remove_fuel(0,user)) - playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) - user.visible_message("[user.name] starts to weld the [src.name] to the floor.", \ + playsound(loc, 'sound/items/Welder2.ogg', 50, 1) + user.visible_message("[user.name] starts to weld the [name] to the floor.", \ "You start to weld \the [src] to the floor...", \ "You hear welding.") if(do_after(user,20, target = src)) - if(!src || !WT.isOn()) return - state = 2 + if(!src || !WT.isOn()) + return + state = FG_WELDED to_chat(user, "You weld the field generator to the floor.") - else - return - if(2) + + if(FG_WELDED) if(WT.remove_fuel(0,user)) - playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) - user.visible_message("[user.name] starts to cut the [src.name] free from the floor.", \ + playsound(loc, 'sound/items/Welder2.ogg', 50, 1) + user.visible_message("[user.name] starts to cut the [name] free from the floor.", \ "You start to cut \the [src] free from the floor...", \ "You hear welding.") if(do_after(user,20, target = src)) - if(!src || !WT.isOn()) return - state = 1 + if(!src || !WT.isOn()) + return + state = FG_SECURED to_chat(user, "You cut \the [src] free from the floor.") - else - return + else - ..() + return ..() /obj/machinery/field/generator/emp_act() @@ -164,30 +148,35 @@ field_generator power level display /obj/machinery/field/generator/bullet_act(obj/item/projectile/Proj) if(Proj.flag != "bullet") - power += Proj.damage - update_icon() + power = min(power + Proj.damage, field_generator_max_power) + check_power_level() return 0 /obj/machinery/field/generator/Destroy() - src.cleanup() + cleanup() return ..() +/obj/machinery/field/generator/proc/check_power_level() + var/new_level = round(num_power_levels * power / field_generator_max_power) + if(new_level != power_level) + power_level = new_level + update_icon() /obj/machinery/field/generator/proc/turn_off() - active = 0 + active = FG_OFFLINE spawn(1) - src.cleanup() - while(warming_up>0 && !active) + cleanup() + while(warming_up > 0 && !active) sleep(50) warming_up-- update_icon() /obj/machinery/field/generator/proc/turn_on() - active = 1 + active = FG_CHARGING spawn(1) - while(warming_up<3 && active) + while(warming_up < 3 && active) sleep(50) warming_up++ update_icon() @@ -196,44 +185,35 @@ field_generator power level display /obj/machinery/field/generator/proc/calc_power() - if(Varpower) - return 1 + var/power_draw = 2 + fields.len - update_icon() - if(src.power > field_generator_max_power) - src.power = field_generator_max_power - - var/power_draw = 2 - for(var/obj/machinery/field/containment/F in fields) - if(isnull(F)) - continue - power_draw++ - if(draw_power(round(power_draw/2,1))) + if(draw_power(round(power_draw/2, 1))) + check_power_level() return 1 else - visible_message("The [src.name] shuts down!", "You hear something shutting down.") + visible_message("The [name] shuts down!", "You hear something shutting down.") turn_off() investigate_log("ran out of power and deactivated","singulo") - src.power = 0 + power = 0 + check_power_level() return 0 //This could likely be better, it tends to start loopin if you have a complex generator loop setup. Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport /obj/machinery/field/generator/proc/draw_power(draw = 0, failsafe = 0, obj/machinery/field/generator/G = null, obj/machinery/field/generator/last = null) - if(Varpower) - return 1 - if((G && G == src) || (failsafe >= 8))//Loopin, set fail + if((G && (G == src)) || (failsafe >= 8))//Loopin, set fail return 0 else failsafe++ - if(src.power >= draw)//We have enough power - src.power -= draw + + if(power >= draw)//We have enough power + power -= draw return 1 + else//Need more power - draw -= src.power - src.power = 0 - for(var/obj/machinery/field/generator/FG in connected_gens) - if(isnull(FG)) - continue + draw -= power + power = 0 + for(var/CG in connected_gens) + var/obj/machinery/field/generator/FG = CG if(FG == last)//We just asked you continue if(G)//Another gen is askin for power and we dont have it @@ -249,7 +229,7 @@ field_generator power level display /obj/machinery/field/generator/proc/start_fields() - if(!src.state == 2 || !anchored) + if(state != FG_WELDED || !anchored) turn_off() return spawn(1) @@ -260,82 +240,73 @@ field_generator power level display setup_field(4) spawn(4) setup_field(8) - src.active = 2 + spawn(5) + active = FG_ONLINE /obj/machinery/field/generator/proc/setup_field(NSEW) - var/turf/T = src.loc - var/obj/machinery/field/generator/G + var/turf/T = loc + if(!istype(T)) + return 0 + + var/obj/machinery/field/generator/G = null var/steps = 0 if(!NSEW)//Make sure its ran right - return - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator + return 0 + for(var/dist in 0 to 7) // checks out to 8 tiles away for another generator T = get_step(T, NSEW) if(T.density)//We cant shoot a field though this return 0 - for(var/atom/A in T.contents) - if(ismob(A)) - continue - if(!istype(A,/obj/machinery/field/generator)) - if((istype(A,/obj/machinery/door)||istype(A,/obj/machinery/the_singularitygen))&&(A.density)) - return 0 - steps += 1 + G = locate(/obj/machinery/field/generator) in T - if(!isnull(G)) + if(G) steps -= 1 if(!G.active) return 0 break - if(isnull(G)) - return - T = src.loc - for(var/dist = 0, dist < steps, dist += 1) // creates each field tile + + for(var/TC in T.contents) + var/atom/A = TC + if(ismob(A)) + continue + if(A.density) + return 0 + + steps++ + + if(!G) + return 0 + + T = loc + for(var/dist in 0 to steps) // creates each field tile var/field_dir = get_dir(T,get_step(G.loc, NSEW)) T = get_step(T, NSEW) if(!locate(/obj/machinery/field/containment) in T) var/obj/machinery/field/containment/CF = new/obj/machinery/field/containment() CF.set_master(src,G) - fields += CF - G.fields += CF CF.loc = T CF.dir = field_dir - for(var/mob/living/L in CF.loc) + fields += CF + G.fields += CF + for(var/mob/living/L in T) CF.Crossed(L) - var/listcheck = 0 - for(var/obj/machinery/field/generator/FG in connected_gens) - if(isnull(FG)) - continue - if(FG == G) - listcheck = 1 - break - if(!listcheck) - connected_gens.Add(G) - listcheck = 0 - for(var/obj/machinery/field/generator/FG2 in G.connected_gens) - if(isnull(FG2)) - continue - if(FG2 == src) - listcheck = 1 - break - if(!listcheck) - G.connected_gens.Add(src) + + connected_gens |= G + G.connected_gens |= src + update_icon() /obj/machinery/field/generator/proc/cleanup() clean_up = 1 - for(var/obj/machinery/field/containment/F in fields) - if(isnull(F)) - continue + for(var/F in fields) qdel(F) - fields = list() - for(var/obj/machinery/field/generator/FG in connected_gens) - if(isnull(FG)) - continue - FG.connected_gens.Remove(src) + + for(var/CG in connected_gens) + var/obj/machinery/field/generator/FG = CG + FG.connected_gens -= src if(!FG.clean_up)//Makes the other gens clean up as well FG.cleanup() - connected_gens.Remove(FG) - connected_gens = list() + connected_gens -= FG clean_up = 0 update_icon() @@ -359,3 +330,11 @@ field_generator power level display /obj/machinery/field/generator/bump_field(atom/movable/AM as mob|obj) if(fields.len) ..() + +#undef FG_UNSECURED +#undef FG_SECURED +#undef FG_WELDED + +#undef FG_OFFLINE +#undef FG_CHARGING +#undef FG_ONLINE diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index ce0d22c4165..2fa6facdab0 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -27,6 +27,7 @@ var/last_warning var/consumedSupermatter = 0 //If the singularity has eaten a supermatter shard and can go to stage six allow_spin = 0 + burn_state = LAVA_PROOF /obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0) //CARN: admin-alert for chuckle-fuckery. @@ -148,17 +149,18 @@ dissipate_delay = 10 dissipate_track = 0 dissipate_strength = 1 - if(STAGE_TWO)//1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them - current_size = STAGE_TWO - icon = 'icons/effects/96x96.dmi' - icon_state = "singularity_s3" - pixel_x = -32 - pixel_y = -32 - grav_pull = 6 - consume_range = 1 - dissipate_delay = 5 - dissipate_track = 0 - dissipate_strength = 5 + if(STAGE_TWO) + if((check_turfs_in(1,1))&&(check_turfs_in(2,1))&&(check_turfs_in(4,1))&&(check_turfs_in(8,1))) + current_size = STAGE_TWO + icon = 'icons/effects/96x96.dmi' + icon_state = "singularity_s3" + pixel_x = -32 + pixel_y = -32 + grav_pull = 6 + consume_range = 1 + dissipate_delay = 5 + dissipate_track = 0 + dissipate_strength = 5 if(STAGE_THREE) if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2))) current_size = STAGE_THREE @@ -237,22 +239,22 @@ /obj/singularity/proc/eat() set background = BACKGROUND_ENABLED - for(var/tile in spiral_range_turfs(grav_pull, src, 1)) + for(var/tile in spiral_range_turfs(grav_pull, src)) var/turf/T = tile - if(!T) + if(!T || !isturf(loc)) continue if(get_dist(T, src) > consume_range) T.singularity_pull(src, current_size) else consume(T) for(var/thing in T) - var/atom/movable/X = thing - if(get_dist(X, src) > consume_range) - X.singularity_pull(src, current_size) - else - consume(X) + if(isturf(loc) && thing != src) + var/atom/movable/X = thing + if(get_dist(X, src) > consume_range) + X.singularity_pull(src, current_size) + else + consume(X) CHECK_TICK - return /obj/singularity/proc/consume(var/atom/A) var/gain = A.singularity_act(current_size) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 66e2e5d68b4..75f88f9b751 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -433,6 +433,7 @@ return 1 /obj/machinery/power/smes/proc/ion_act() + // TODO: Tie into space manager if(src.z in config.station_levels) if(prob(1)) //explosion for(var/mob/M in viewers(src)) diff --git a/code/modules/power/supermatter/sm_crystals.dm b/code/modules/power/supermatter/sm_crystals.dm deleted file mode 100644 index cb9448a2b2e..00000000000 --- a/code/modules/power/supermatter/sm_crystals.dm +++ /dev/null @@ -1,179 +0,0 @@ -//separate dm since hydro is getting bloated already - -/obj/effect/supermatter_crystal - name = "supermatter growth" - anchored = 1 - opacity = 0 - density = 0 - icon = 'icons/obj/lighting.dmi' - icon_state = "supermatter_crystalf" - layer = 2.1 - light_color = "#8A8A00" - - var/endurance = 100 - var/delay = 1200 - var/floor = 0 - var/spreadChance = 10 - var/spreadIntoAdjacentChance = 10 - var/lastTick = 0 - var/spreaded = 1 - var/deleted = 0 - -/obj/effect/supermatter_crystal/single - spreadChance = 0 - -/obj/effect/supermatter_crystal/New() - ..() - light_color = "#8A8A00" - - dir = CalcDir() - - if(!floor) - switch(dir) //offset to make it be on the wall rather than on the floor - if(NORTH) - pixel_y = 32 - if(SOUTH) - pixel_y = -32 - if(EAST) - pixel_x = 32 - if(WEST) - pixel_x = -32 - icon_state = "supermatter_crystal" - else - if( prob( 10 )) // Only 10% of all floor crystals survive, so there's not a forest of 'em - icon_state = "supermatter_crystalf" - name = "supermatter crystal" - density = 1 - else - deleted = 1 - del( src ) - - processing_objects += src - - set_light(3) - lastTick = world.timeofday - -/obj/effect/supermatter_crystal/Del() - if( !deleted ) - visible_message("\red \The [src] shatters!") - new /obj/item/weapon/shard/supermatter( src.loc ) - - processing_objects -= src - ..() - -/obj/effect/supermatter_crystal/process() - if(!spreaded) - return - - if(((world.timeofday - lastTick) > delay) || ((world.timeofday - lastTick) < 0)) - lastTick = world.timeofday - spreaded = 0 - - for(var/mob/living/l in range( src, 2 )) - var/rads = 5 - l.apply_effect(rads, IRRADIATE) - - for(var/i=1,i<=3,i++) - if(prob(spreadChance)) - var/list/possibleLocs = list() - var/spreadsIntoAdjacent = 0 - - if(prob(spreadIntoAdjacentChance)) - spreadsIntoAdjacent = 1 - - for(var/turf/simulated/floor/floor in view(3,src)) - if(spreadsIntoAdjacent || !locate(/obj/effect/supermatter_crystal) in view(1,floor)) - possibleLocs += floor - - if(!possibleLocs.len) - break - - var/turf/newLoc = pick(possibleLocs) - - var/crystalCount = 0 //hacky - var/placeCount = 1 - for(var/obj/effect/supermatter_crystal/shroom in newLoc) - crystalCount++ - for(var/wallDir in cardinal) - var/turf/isWall = get_step(newLoc,wallDir) - if(isWall.density) - placeCount++ - if(crystalCount >= placeCount) - continue - - var/obj/effect/supermatter_crystal/child = new /obj/effect/supermatter_crystal(newLoc) - if( child ) - child.delay = delay - child.endurance = endurance - - spreaded++ - -/obj/effect/supermatter_crystal/proc/CalcDir(turf/location = loc) - for(var/wallDir in cardinal) - var/turf/newTurf = get_step(location,wallDir) - if(newTurf.density) - return wallDir - -/* - var/direction = 16 - - for(var/wallDir in cardinal) - var/turf/newTurf = get_step(location,wallDir) - if(newTurf.density) - direction |= wallDir - - for(var/obj/effect/supermatter_crystal/crystal in location) - if(crystal == src) - continue - if(crystal.floor) //special - direction &= ~16 - else - direction &= ~crystal.dir - - var/list/dirList = list() - - for(var/i=1,i<=16,i <<= 1) - if(direction & i) - dirList += i - - if(dirList.len) - var/newDir = pick(dirList) - if(newDir == 16) - floor = 1 - newDir = 1 - return newDir -*/ - floor = 1 - return 1 - -/obj/effect/supermatter_crystal/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - - endurance -= W.force - - CheckEndurance() - -/obj/effect/supermatter_crystal/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if(prob(50)) - qdel(src) - return - if(3.0) - if(prob(5)) - qdel(src) - return - else - return - -/obj/effect/supermatter_crystal/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - endurance -= 5 - CheckEndurance() - -/obj/effect/supermatter_crystal/proc/CheckEndurance() - if(endurance <= 0) - qdel(src) \ No newline at end of file diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index af3d37e4481..14407ef9202 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -1,7 +1,7 @@ #define TESLA_DEFAULT_POWER 1738260 #define TESLA_MINI_POWER 869130 -var/list/blacklisted_tesla_types = list(/obj/machinery/atmospherics, +var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics, /obj/machinery/power/emitter, /obj/machinery/field/generator, /mob/living/simple_animal, @@ -15,7 +15,7 @@ var/list/blacklisted_tesla_types = list(/obj/machinery/atmospherics, /obj/machinery/field/containment, /obj/structure/disposalpipe, /obj/structure/sign, - /obj/machinery/gateway) + /obj/machinery/gateway)) /obj/singularity/energy_ball name = "energy ball" @@ -175,7 +175,7 @@ var/list/blacklisted_tesla_types = list(/obj/machinery/atmospherics, closest_atom = A closest_dist = dist - else if(closest_grounding_rod || is_type_in_list(A, blacklisted_tesla_types)) + else if(closest_grounding_rod || is_type_in_typecache(A, blacklisted_tesla_types)) continue else if(istype(A, /mob/living)) diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 526876ca519..a97bde454c6 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -186,7 +186,7 @@ /obj/item/ammo_box/magazine/m45 name = "handgun magazine (.45)" - icon_state = "45-8" + icon_state = "45" ammo_type = /obj/item/ammo_casing/c45 caliber = ".45" max_ammo = 8 diff --git a/code/modules/projectiles/guns/energy/telegun.dm b/code/modules/projectiles/guns/energy/telegun.dm index 2155a1cf0a1..c280fe59903 100644 --- a/code/modules/projectiles/guns/energy/telegun.dm +++ b/code/modules/projectiles/guns/energy/telegun.dm @@ -23,7 +23,8 @@ var/turf/T = get_turf(R) if(!T) continue - if((T.z in config.admin_levels) || T.z > 7) + // TODO: Tie into space manager + if((T.z in config.admin_levels) || T.z > ZLEVEL_EMPTY) continue if(R.syndicate == 1) continue diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 5a8fa77e268..42a7c6a9c7b 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -11,6 +11,7 @@ hitsound = 'sound/weapons/pierce.ogg' var/hitsound_wall = "" pressure_resistance = INFINITY + burn_state = LAVA_PROOF var/def_zone = "" //Aiming at var/mob/firer = null//Who shot it var/obj/item/ammo_casing/ammo_casing = null diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index ecb54b9c1f0..8c40044ad2d 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -56,8 +56,8 @@ /obj/item/projectile/bullet/incendiary /obj/item/projectile/bullet/incendiary/on_hit(var/atom/target, var/blocked = 0) - ..() - if(istype(target, /mob/living/carbon)) + . = ..() + if(iscarbon(target)) var/mob/living/carbon/M = target M.adjust_fire_stacks(4) M.IgniteMob() diff --git a/code/modules/reagents/newchem/Blob-Reagents.dm b/code/modules/reagents/newchem/Blob-Reagents.dm index d3ebcc447b5..fa5e9747e34 100644 --- a/code/modules/reagents/newchem/Blob-Reagents.dm +++ b/code/modules/reagents/newchem/Blob-Reagents.dm @@ -31,7 +31,7 @@ /datum/reagent/blob/boiling_oil/reaction_mob(mob/living/M, method=TOUCH, volume) if(method == TOUCH) - M.adjust_fire_stacks(round(volume/12)) + M.adjust_fire_stacks(round(volume/10)) volume = ..() M.apply_damage(0.6*volume, BURN) M.IgniteMob() diff --git a/code/modules/reagents/newchem/disease.dm b/code/modules/reagents/newchem/disease.dm index 6f8e7fd6308..def94ba9a2c 100644 --- a/code/modules/reagents/newchem/disease.dm +++ b/code/modules/reagents/newchem/disease.dm @@ -122,6 +122,25 @@ qdel(ate_heart) ..() +//virus-specific symptom reagents + +/datum/reagent/synaphydramine + name = "Diphen-Synaptizine" + id = "synaphydramine" + description = "Reduces drowsiness and hallucinations while also purging histamine from the body." + color = "#EC536D" // rgb: 236, 83, 109 + +/datum/reagent/synaphydramine/on_mob_life(mob/living/M) + M.drowsyness = max(M.drowsyness-5, 0) + if(holder.has_reagent("lsd")) + holder.remove_reagent("lsd", 5) + if(holder.has_reagent("histamine")) + holder.remove_reagent("histamine", 5) + M.hallucination = max(0, M.hallucination - 10) + if(prob(30)) + M.adjustToxLoss(1) + ..() + //virus food /datum/reagent/virus_food name = "Virus Food" diff --git a/code/modules/reagents/newchem/pyro.dm b/code/modules/reagents/newchem/pyro.dm index 7afdc564647..6dece72544c 100644 --- a/code/modules/reagents/newchem/pyro.dm +++ b/code/modules/reagents/newchem/pyro.dm @@ -37,8 +37,9 @@ min_temp = 424 /datum/reagent/clf3/on_mob_life(mob/living/M) - M.adjust_fire_stacks(4) - M.adjustFireLoss(0.35*M.fire_stacks) + M.adjust_fire_stacks(2) + var/burndmg = max(0.3*M.fire_stacks, 0.3) + M.adjustFireLoss(burndmg) ..() /datum/chemical_reaction/clf3/on_reaction(datum/reagents/holder, created_volume) @@ -66,7 +67,7 @@ /datum/reagent/clf3/reaction_mob(mob/living/M, method=TOUCH, volume) if(method == TOUCH) - M.adjust_fire_stacks(5) + M.adjust_fire_stacks(min(volume/5, 10)) M.IgniteMob() M.bodytemperature += 30 @@ -416,10 +417,14 @@ for(var/turf/simulated/turf in range(min(created_volume/10,4),T)) new /obj/effect/hotspot(turf) +/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, volume) + M.IgniteMob() + ..() + /datum/reagent/phlogiston/on_mob_life(mob/living/M) M.adjust_fire_stacks(1) - M.IgniteMob() - M.adjustFireLoss(0.2*M.fire_stacks) + var/burndmg = max(0.3*M.fire_stacks, 0.3) + M.adjustFireLoss(burndmg) ..() /datum/reagent/napalm @@ -436,7 +441,7 @@ /datum/reagent/napalm/reaction_mob(mob/living/M, method=TOUCH, volume) if(method == TOUCH) - M.adjust_fire_stacks(7) + M.adjust_fire_stacks(min(volume/4, 20)) /datum/chemical_reaction/napalm name = "Napalm" @@ -539,8 +544,11 @@ // Put out fire if(method == TOUCH) M.adjust_fire_stacks(-(volume / 5)) // more effective than water - if(M.fire_stacks <= 0) - M.ExtinguishMob() + M.ExtinguishMob() + +/datum/reagent/firefighting_foam/reaction_obj(obj/O, volume) + if(istype(O)) + O.extinguish() /datum/reagent/firefighting_foam/reaction_turf(turf/simulated/T, volume) if(!istype(T)) @@ -555,18 +563,6 @@ T.assume_air(lowertemp) qdel(hotspot) -/datum/reagent/firefighting_foam/reaction_obj(obj/O, volume) - var/turf/simulated/T = get_turf(O) - if(!istype(T)) - return - var/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot) - var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles()) - lowertemp.temperature = max(min(lowertemp.temperature-2000,lowertemp.temperature / 2), 0) - lowertemp.react() - T.assume_air(lowertemp) - qdel(hotspot) - /datum/chemical_reaction/clf3_firefighting name = "clf3_firefighting" id = "clf3_firefighting" diff --git a/code/modules/reagents/oldchem/reagents/reagents_water.dm b/code/modules/reagents/oldchem/reagents/reagents_water.dm index a2ec51f1811..bbfcbeb8142 100644 --- a/code/modules/reagents/oldchem/reagents/reagents_water.dm +++ b/code/modules/reagents/oldchem/reagents/reagents_water.dm @@ -20,9 +20,7 @@ // Put out fire if(method == TOUCH) M.adjust_fire_stacks(-(volume / 10)) - if(M.fire_stacks <= 0) - M.ExtinguishMob() - return + M.ExtinguishMob() /datum/reagent/water/reaction_turf(turf/simulated/T, volume) if(!istype(T)) @@ -42,15 +40,9 @@ qdel(hotspot) /datum/reagent/water/reaction_obj(obj/O, volume) - var/turf/simulated/T = get_turf(O) - if(istype(T)) - var/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot) - var/datum/gas_mixture/lowertemp = T.remove_air( T.air.total_moles() ) - lowertemp.temperature = max(min(lowertemp.temperature-2000,lowertemp.temperature / 2), 0) - lowertemp.react() - T.assume_air(lowertemp) - qdel(hotspot) + if(istype(O)) + O.extinguish() + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube)) var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = O if(!cube.wrapped) @@ -274,7 +266,7 @@ /datum/reagent/holywater/on_mob_life(mob/living/M) M.jitteriness = max(M.jitteriness-5,0) if(current_cycle >= 30) // 12 units, 60 seconds @ metabolism 0.4 units & tick rate 2.0 sec - M.stuttering += 4 + M.stuttering = min(M.stuttering+4, 20) M.Dizzy(5) if(iscultist(M) && prob(5)) M.say(pick("Av'te Nar'sie","Pa'lid Mors","INO INO ORA ANA","SAT ANA!","Daim'niodeis Arc'iai Le'eones","Egkau'haom'nai en Chaous","Ho Diak'nos tou Ap'iron","R'ge Na'sie","Diabo us Vo'iscum","Si gn'um Co'nu")) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 9024904f7e3..39945505aed 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -64,7 +64,7 @@ // attack by item places it in to disposal /obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user, params) - if(stat & BROKEN || !I || !user || ((I.flags & NODROP) && !istype(I, /obj/item/weapon/storage/bag/trash/cyborg))) + if(stat & BROKEN || !I || !user) return src.add_fingerprint(user) @@ -144,7 +144,8 @@ if(!I) return - user.drop_item() + if(!user.drop_item()) + return if(I) I.loc = src diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 02b13b903f2..ddcb3f2f399 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -117,6 +117,7 @@ flags = NOBLUDGEON amount = 25 max_amount = 25 + burn_state = FLAMMABLE /obj/item/stack/packageWrap/afterattack(var/obj/target as obj, mob/user as mob, proximity) diff --git a/code/modules/research/xenoarchaeology/machinery/artifact_harvester.dm b/code/modules/research/xenoarchaeology/machinery/artifact_harvester.dm index 9819275c0d1..a307076b374 100644 --- a/code/modules/research/xenoarchaeology/machinery/artifact_harvester.dm +++ b/code/modules/research/xenoarchaeology/machinery/artifact_harvester.dm @@ -142,7 +142,7 @@ else if(articount > 1) - state("Cannot harvest. Too many artifacts on the pad.") + atom_say("Cannot harvest. Too many artifacts on the pad.") else if(analysed) cur_artifact = analysed diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index e3a59183abf..19065faad8c 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -342,6 +342,7 @@ C.color = "#000080" C.max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT C.heat_protection = C.body_parts_covered + C.burn_state = FIRE_PROOF uses -- if(!uses) qdel(src) @@ -402,6 +403,8 @@ return 0 if(O.mind && O.mind.current && O.mind.current.stat != DEAD) return 0 + if(!O.can_reenter_corpse) + return 0 if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) return 0 return 1 diff --git a/code/modules/security_levels/security levels.dm b/code/modules/security_levels/security levels.dm index 61b0d3ce0dc..328a19ac034 100644 --- a/code/modules/security_levels/security levels.dm +++ b/code/modules/security_levels/security levels.dm @@ -37,6 +37,7 @@ CC.post_status("alert", "outline") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") @@ -53,6 +54,7 @@ CC.post_status("alert", "outline") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") @@ -65,6 +67,7 @@ security_level = SEC_LEVEL_RED var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world + // TODO: Tie into space manager if(R && (R.z in config.station_levels)) R.locked = 0 R.update_icon() @@ -74,6 +77,7 @@ CC.post_status("alert", "redalert") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") @@ -85,12 +89,14 @@ move_gamma_ship() if(security_level < SEC_LEVEL_RED) - for(var/obj/machinery/door/airlock/highsecurity/red/R in world) + for(var/obj/machinery/door/airlock/highsecurity/red/R in airlocks) + // TODO: Tie into space manager if((R.z in config.station_levels)) R.locked = 0 R.update_icon() - for(var/obj/machinery/door/airlock/hatch/gamma/H in world) + for(var/obj/machinery/door/airlock/hatch/gamma/H in airlocks) + // TODO: Tie into space manager if((H.z in config.station_levels)) H.locked = 0 H.update_icon() @@ -100,6 +106,7 @@ CC.post_status("alert", "gammaalert") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma") @@ -114,6 +121,7 @@ CC.post_status("alert", "epsilonalert") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon") @@ -127,6 +135,7 @@ CC.post_status("alert", "deltaalert") for(var/obj/machinery/firealarm/FA in world) + // TODO: Tie into space manager if((FA.z in config.contact_levels)) FA.overlays = list() FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") @@ -189,4 +198,4 @@ set_security_level(2) /mob/verb/set_thing3() set_security_level(3) -*/ \ No newline at end of file +*/ diff --git a/code/modules/shuttle/assault_pod.dm b/code/modules/shuttle/assault_pod.dm index fe3d059a08a..40e7aa05aa0 100644 --- a/code/modules/shuttle/assault_pod.dm +++ b/code/modules/shuttle/assault_pod.dm @@ -6,6 +6,7 @@ height = 7 /obj/docking_port/mobile/assault_pod/request() + // TODO: Tie into space manager if(z == initial(src.z)) //No launching pods that have already launched return ..() diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 6d1b7689ce5..7fd8186ab5b 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -209,6 +209,7 @@ if(time_left <= 0 && !shuttle_master.emergencyNoEscape) //move each escape pod to its corresponding transit dock for(var/obj/docking_port/mobile/pod/M in shuttle_master.mobile) + // TODO: Tie into space manager if(M.z == ZLEVEL_STATION) //Will not launch from the mine/planet M.enterTransit() //now move the actual emergency shuttle to its transit dock diff --git a/code/modules/space_management/heap_space_level.dm b/code/modules/space_management/heap_space_level.dm new file mode 100644 index 00000000000..8d5a3971ba1 --- /dev/null +++ b/code/modules/space_management/heap_space_level.dm @@ -0,0 +1,15 @@ +// This represents a level we can carve up as we please, and hand out +// chunks of to whatever requests it +/datum/space_level/heap + var/datum/space_chunk/top + linkage = UNAFFECTED + +/datum/space_level/heap/New() + ..() + top = new + +/datum/space_level/heap/proc/request(width, height) + return 1 // All are welcome! At least until I add code for this + +/datum/zlevel/heap/proc/allocate(width, height) + return diff --git a/code/modules/space_management/space_chunk.dm b/code/modules/space_management/space_chunk.dm new file mode 100644 index 00000000000..b7764e5673e --- /dev/null +++ b/code/modules/space_management/space_chunk.dm @@ -0,0 +1,24 @@ +/datum/space_chunk + var/x + var/y + var/width + var/height + var/zpos + +/datum/space_chunk/New(w, h, z, new_x, new_y) + x = new_x + y = new_y + zpos = z + width = w + height = h + +/datum/space_chunk/proc/check_sanity() + var/i_am_sane = 1 + i_am_sane |= (x > 0) + i_am_sane |= (y > 0) + i_am_sane |= (x <= world.maxx) + i_am_sane |= (y <= world.maxy) + return i_am_sane + +/datum/space_chunk/proc/return_turfs() + return diff --git a/code/modules/space_management/space_level.dm b/code/modules/space_management/space_level.dm new file mode 100644 index 00000000000..6b7654cd504 --- /dev/null +++ b/code/modules/space_management/space_level.dm @@ -0,0 +1,125 @@ +/datum/space_level + var/name = "Your config settings failed, you need to fix this for the datum space levels to work" + var/zpos = 1 + var/flags = 0 // We'll use this to keep track of whether you can teleport/etc + + // Map transition stuff + var/list/neighbors = list() + // # How this level connects with others. See __MAP_DEFINES.dm for defines + var/linkage = SELFLOOPING + // # imaginary placements on the grid - these reflect the point it is linked to + var/xi + var/yi + var/list/transit_north = list() + var/list/transit_south = list() + var/list/transit_east = list() + var/list/transit_west = list() + + // Init deferral stuff + var/dirt_count = 0 + var/list/init_list = list() + +/datum/space_level/New(z, name, transition_type = SELFLOOPING) + zpos = z + set_linkage(transition_type) + build_space_destination_arrays() + +/datum/space_level/proc/build_space_destination_arrays() + var/timer = start_watch() + log_debug("Starting to build space destination arrays for z level '[zpos]'...") + for(var/turf/space/S in get_turfs()) + + // Bottom border + if(S.y <= TRANSITIONEDGE) + transit_south |= S + continue + + // Top border + if(S.y >= (world.maxy - TRANSITIONEDGE - 1)) + transit_north |= S + continue + + // Left border + if(S.x <= TRANSITIONEDGE) + transit_west |= S + continue + + // Right border + if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) + transit_east |= S + continue + log_debug("Building space destination arrays complete, took [stop_watch(timer)]s.") + +/datum/space_level/proc/get_turfs() + return block(locate(1, 1, zpos), locate(world.maxx, world.maxy, zpos)) + +/datum/space_level/proc/set_linkage(transition_type) + linkage = transition_type + if(transition_type == SELFLOOPING) + link_to_self() // `link_to_self` is defined in space_transitions.dm + + +/datum/space_level/proc/resume_init() + if(dirt_count > 0) + throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'") + log_debug("Releasing freeze on z-level '[zpos]'!") + log_debug("Beginning initialization!") + var/list/our_atoms = init_list // OURS NOW!!! (Keeping this list to ourselves will prevent hijack) + init_list = list() + var/list/late_maps = list() + var/list/pipes = list() + var/list/cables = list() + var/watch = start_watch() + for(var/schmoo in our_atoms) + var/atom/movable/AM = schmoo + if(AM) // to catch stuff like the nuke disk that no longer exists + + // This can mess with our state - we leave these for last + if(istype(AM, /obj/effect/landmark/map_loader)) + late_maps.Add(AM) + continue + AM.initialize() + if(istype(AM, /obj/machinery/atmospherics)) + pipes.Add(AM) + else if(istype(AM, /obj/structure/cable)) + cables.Add(AM) + log_debug("Primary initialization finished in [stop_watch(watch)]s.") + our_atoms.Cut() + if(pipes.len) + do_pipes(pipes) + if(cables.len) + do_cables(cables) + if(late_maps.len) + do_late_maps(late_maps) + +/datum/space_level/proc/do_pipes(list/pipes) + var/watch = start_watch() + log_debug("Building pipenets on z-level '[zpos]'!") + for(var/schmoo in pipes) + var/obj/machinery/atmospherics/machine = schmoo + if(machine) + machine.build_network() + pipes.Cut() + log_debug("Took [stop_watch(watch)]s") + +/datum/space_level/proc/do_cables(list/cables) + var/watch = start_watch() + log_debug("Building powernets on z-level '[zpos]'!") + for(var/schmoo in cables) + var/obj/structure/cable/C = schmoo + if(C) + makepowernet_for(C) + cables.Cut() + log_debug("Took [stop_watch(watch)]s") + +/datum/space_level/proc/do_late_maps(list/late_maps) + var/watch = start_watch() + log_debug("Loading map templates on z-level '[zpos]'!") + space_manager.add_dirt(zpos) // Let's not repeatedly resume init for each template + for(var/schmoo in late_maps) + var/obj/effect/landmark/map_loader/ML = schmoo + if(ML) + ML.initialize() + late_maps.Cut() + space_manager.remove_dirt(zpos) + log_debug("Took [stop_watch(watch)]s") diff --git a/code/modules/space_management/space_transition.dm b/code/modules/space_management/space_transition.dm new file mode 100644 index 00000000000..469365e4023 --- /dev/null +++ b/code/modules/space_management/space_transition.dm @@ -0,0 +1,412 @@ +//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube + +#define Z_LEVEL_NORTH "1" +#define Z_LEVEL_SOUTH "2" +#define Z_LEVEL_EAST "4" +#define Z_LEVEL_WEST "8" + +/proc/get_opposite_direction(direction) + switch(direction) + if(Z_LEVEL_NORTH) + return Z_LEVEL_SOUTH + if(Z_LEVEL_SOUTH) + return Z_LEVEL_NORTH + if(Z_LEVEL_EAST) + return Z_LEVEL_WEST + if(Z_LEVEL_WEST) + return Z_LEVEL_EAST + +/datum/space_level + var/list/direction_cache = list() + +/datum/space_level/proc/link_to_self() + neighbors = list() + var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST) + for(var/A in L) + neighbors[A] = src + +// This proc takes another space level, and establishes a connection between the +// two depending on how the `xi` and the `yi` values compare +/datum/space_level/proc/link_levels(datum/space_level/S) + if(S.xi == xi) + if(S.yi == yi+1) + add_connection(S, Z_LEVEL_NORTH) + else if(S.yi == yi-1) + add_connection(S, Z_LEVEL_SOUTH) + else if(S.yi == yi) + if(S.xi == xi+1) + add_connection(S, Z_LEVEL_EAST) + else if(S.xi == xi-1) + add_connection(S, Z_LEVEL_WEST) + else // yell about evil wizards, this shouldn't happen + log_debug("Two z levels attempted to link, but were not adjacent! Our z:([xi],[yi]). Other z:([S.xi],[S.yi])") + +// Do this before setting up new connections, or the old ones will haunt you +/datum/space_level/proc/reset_connections() + neighbors.Cut() + direction_cache.Cut() + +// `direction` here is the direction from `src` to `S` +/datum/space_level/proc/add_connection(datum/space_level/S, direction) + var/oppose = get_opposite_direction(direction) + neighbors[direction] = S + S.neighbors[oppose] = src + + +// The "direction cache" will need updating if a +/datum/space_level/proc/get_connection(direction) + if(direction in neighbors) + return neighbors[direction] + var/use_direction_cache = 0 + if(use_direction_cache) + if(direction in direction_cache) + return direction_cache[direction] + + // It's in a direction that loops - so we step as far in the opposite direction to get where to wrap to + var/datum/space_level/S = src + var/oppose = get_opposite_direction(direction) + // Loop all the way in the other direction that we can + while(S.neighbors[oppose]) + if(S.neighbors[oppose] == src) // we've got a tesseract, boys + CRASH("Tesseract formed when routing connections between z levels. Culprit: z level '[S.zpos]' to '[src.zpos]', direction [oppose]") + S = S.neighbors[oppose] + + if(use_direction_cache) + direction_cache[direction] = S + return S + + +/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else + var/list/neighbors = list() + var/x + var/y + var/datum/space_level/spl + +/datum/point/New(nx, ny) + x = nx + y = ny + +/datum/point/proc/hash() + return "([x],[y])" + +// This is called only on `filled_nodes` - meaning we have a guarantee that +// it is already surrounded on all sides +/datum/point/proc/set_neighbors(datum/spacewalk_grid/SW) + neighbors.Cut() + neighbors |= SW.get(x+1, y, allow_empty = 1) + neighbors |= SW.get(x-1, y, allow_empty = 1) + neighbors |= SW.get(x, y+1, allow_empty = 1) + neighbors |= SW.get(x, y-1, allow_empty = 1) + +// Updates variables of the space level +/datum/point/proc/set_space_level(datum/space_level/S) + spl = S + S.xi = x + S.yi = y + for(var/datum/point/P in neighbors) + if(istype(P.spl)) + // Since each time this proc is called, it is the first time + // that the z level is added to the grid, we know for certain + // that no other z level has this as its neighbor + spl.link_levels(P.spl) + +// Returns a list of all neighbors that don't have a space level yet +// If a node doesn't exist yet, it will create it +// This is only called for nodes within the `available_nodes` list +/datum/point/proc/get_empty_neighbors(datum/spacewalk_grid/SW) + var/list/result + var/datum/point/up = SW.get(x, y+1, allow_empty = 1) + var/datum/point/down = SW.get(x, y-1, allow_empty = 1) + var/datum/point/left = SW.get(x-1, y, allow_empty = 1) + var/datum/point/right = SW.get(x+1, y, allow_empty = 1) + if(isnull(up)) + up = new(x, y+1) + SW.add_available_node(up) + + if(isnull(down)) + down = new(x, y-1) + SW.add_available_node(down) + + if(isnull(left)) + left = new(x-1, y) + SW.add_available_node(left) + + if(isnull(right)) + right = new(x+1, y) + SW.add_available_node(right) + + // Nodes with a space datum are not empty + result = list(up, down, left, right) + for(var/datum/point/thing in result) + if(!isnull(thing.spl)) + result -= thing + return result + +// This looks around itself to see if it has any active nodes within the cardinal directions +/datum/point/proc/has_no_neighbors(datum/spacewalk_grid/SW) + var/result = 1 + if(spl) + return 1 + if(!isnull(SW.get(x+1,y))) + result = 0 + if(!isnull(SW.get(x-1,y))) + result = 0 + if(!isnull(SW.get(x,y+1))) + result = 0 + if(!isnull(SW.get(x,y-1))) + result = 0 + return result + + +/datum/point/proc/deactivate() + if(!spl) + throw EXCEPTION("Attempted to deactivate inactive point") + for(var/direction in spl.neighbors) + var/datum/space_level/S = spl.neighbors[direction] + var/oppose = get_opposite_direction(direction) + S.neighbors.Remove(oppose) + spl.reset_connections() + spl = initial(spl) + +// This is like the old algorithm, except this one +// can expand indefinitely and add new points on the fly + +// The algorithm is: Start in the center, and add all adjacent points to a list of things to select +// Then repeatedly do the cycle of choosing a node next to any previously-selected node, then +// add all points next to your chosen node to the list of things to select +/datum/spacewalk_grid + // This is a list of fully initialized nodes - these have their neighbors + // assigned, and are surrounded + var/list/filled_nodes = list() + // These nodes are not fully initialized - their neighbors field is empty, + // and they do not correspond to a space level + var/list/available_nodes = list() + var/list/all_nodes = list() // filled_nodes | available_nodes + var/min_x = 0 + var/min_y = 0 + var/max_x = 0 + var/max_y = 0 + +/datum/spacewalk_grid/New() + var/datum/point/P = new(0,0) + add_available_node(P) + +/datum/spacewalk_grid/proc/add_available_node(datum/point/P) + var/hash = P.hash() + if(hash in all_nodes) + log_debug("Hash overlap! [hash]") + all_nodes[P.hash()] = P + available_nodes |= P + +// We call this to flag a node as in use - all required variables will be +// ready after this is called +/datum/spacewalk_grid/proc/consume_node(datum/point/P) + filled_nodes |= P + available_nodes -= P + // This proc adds any new neighbors to the list of available nodes + P.get_empty_neighbors(src) + if(min_x > P.x) + min_x = P.x + else if(max_x < P.x) + max_x = P.x + if(min_y > P.y) + min_y = P.y + else if(max_y < P.y) + max_y = P.y + P.set_neighbors(src) + +// You can call this with an active point, to remove it from the grid - +// this is important if you want to separate a z level from the network +/datum/spacewalk_grid/proc/release_node(datum/point/P) + filled_nodes -= P + available_nodes |= P + // Go through each neighbor node, and delete it if it's not + // next to any other active nodes + for(var/datum/point/P2 in P.neighbors) + var/isolated = P2.has_no_neighbors(src) + if(isolated) + available_nodes -= P2 + all_nodes -= P2.hash() + qdel(P) + P.deactivate() + P.neighbors.Cut() + + // Now that we've cleaned out inactive nodes, we will update the bounds + var/datum/point/outer_bound + if(P.x == max_x) + for(var/i = min_y, i <= max_y, i++) + outer_bound = get(P.x, i) + if(!isnull(outer_bound)) // There is still an active node in this column + break + if(isnull(outer_bound)) + max_x-- + + if(P.x == min_x) + for(var/i = min_y, i <= max_y, i++) + outer_bound = get(P.x, i) + if(!isnull(outer_bound)) // There is still an active node in this column + break + if(isnull(outer_bound)) + min_x++ + + if(P.y == max_y) + for(var/i = min_x, i <= max_x, i++) + outer_bound = get(i, P.y) + if(!isnull(outer_bound)) // There is still an active node in this column + break + if(isnull(outer_bound)) + max_y-- + + if(P.y == min_y) + for(var/i = min_x, i <= max_x, i++) + outer_bound = get(i, P.y) + if(!isnull(outer_bound)) // There is still an active node in this column + break + if(isnull(outer_bound)) + min_y++ + + +// If the node isn't in the grid, this will return null +/datum/spacewalk_grid/proc/get(x,y, allow_empty = 0) + var/datum/point/P = all_nodes["([x],[y])"] + if(!allow_empty && !(P in filled_nodes)) + P = null // active nodes only + return P + +/datum/spacewalk_grid/proc/get_width() + return 1 + max_x - min_x + +/datum/spacewalk_grid/proc/get_height() + return 1 + max_y - min_y + +// This function is called repeatedly to build the map +/datum/spacewalk_grid/proc/get_empty_node() + var/datum/point/P = pick(available_nodes) + if(isnull(P)) + throw EXCEPTION("The `available_nodes` list was either empty or contained a null entry") + consume_node(P) + return P + +// This proc substantiates the grid of points used to determine routes between levels +// Separating this from initialization gives us time in which we can add more crosslink z levels +// before we bake in all our connections +/datum/zlev_manager/proc/route_linkage() + var/list/crosslinks = list() + var/datum/space_level/D + for(var/A in z_list) + D = z_list[A] + if(D.linkage == CROSSLINKED) + crosslinks.Add(D) + D.reset_connections() + + // We create an imaginary, square, grid, with dimensions that are + // twice the number of z levels, plus one, per side + + // This is big enough to hold a straight line from the center to any side + // `point_grid` is indexed as a 2 way matrix of these points + // `grid` is a flat list of these same above points + + // Each point represents a possible z level position + var/datum/spacewalk_grid/point_grid = new + // We do this so we can display the way the levels connect later + linkage_map = point_grid + var/datum/point/P + + // Now, we pop entries in a random order from our list of space levels + // and assign its connections based on the grid + while(crosslinks.len) + D = pick(crosslinks) + crosslinks.Remove(D) + // We now choose a point in our imaginary grid adjacent to our current location + P = point_grid.get_empty_node() + // Let our z level know where in the imaginary grid it is + // This will also handle establishing neighborship with other z levels + P.set_space_level(D) + +// A heavy proc - loops through all space turfs and sets its destination +// based on its space level's linkage +// Takes 0.6 seconds per call on my machine - could have each z level +// have its own space turf cache, but I don't want to complicate this more +// than is necessary +/datum/zlev_manager/proc/setup_space_destinations() + var/timer = start_watch() + log_debug("Assigning space turf destinations...") + var/datum/space_level/D + var/datum/space_level/E + var/turf/space/S + for(var/A in z_list) //Define the transistions of the z levels + D = z_list[A] + if(!D.neighbors.len) + continue + // Left border + for(var/B in D.transit_west) + S = B + E = D.get_connection(Z_LEVEL_WEST) + S.destination_z = E.zpos + S.destination_x = world.maxx - TRANSITIONEDGE - 2 + S.destination_y = S.y + + // Right border + for(var/B in D.transit_east) + S = B + E = D.get_connection(Z_LEVEL_EAST) + S.destination_x = TRANSITIONEDGE + 2 + S.destination_y = S.y + S.destination_z = E.zpos + + // Bottom border + for(var/B in D.transit_south) + S = B + E = D.get_connection(Z_LEVEL_SOUTH) + S.destination_x = S.x + S.destination_y = world.maxy - TRANSITIONEDGE - 2 + S.destination_z = E.zpos + + // Top border + for(var/B in D.transit_north) + S = B + E = D.get_connection(Z_LEVEL_NORTH) + S.destination_x = S.x + S.destination_y = TRANSITIONEDGE + 2 + S.destination_z = E.zpos + + log_debug("Assigning space turf destinations complete. Took [stop_watch(timer)]s.") + +// Nothing fancy, just does it all at once +/datum/zlev_manager/proc/do_transition_setup() + route_linkage() + setup_space_destinations() + +// A debugging proc that expresses the map's shape as a bunch of turfs +/datum/zlev_manager/proc/map_as_turfs(turf/center) + // size is odd + // -1, /2 to get distance from the center + // center - radius = bottom left coordinate + var/datum/point/P + var/turf/our_spot + var/grid_desc = "" + for(var/i = linkage_map.min_x, i <= linkage_map.max_x, i++) + for(var/j = linkage_map.min_y, j <= linkage_map.max_y, j++) + P = linkage_map.get(i, j) + our_spot = locate(center.x + i, center.y + j, center.z) + grid_desc = "([i],[j])" + if(!isnull(P)) + our_spot = our_spot.ChangeTurf(/turf/simulated/floor/plating/snow) + grid_desc += ": Z level [P.spl.zpos]. " + var/datum/space_level/up = P.spl.get_connection(Z_LEVEL_NORTH) + var/datum/space_level/down = P.spl.get_connection(Z_LEVEL_SOUTH) + var/datum/space_level/right = P.spl.get_connection(Z_LEVEL_EAST) + var/datum/space_level/left = P.spl.get_connection(Z_LEVEL_WEST) + grid_desc += "Up: [up.zpos], " + grid_desc += "Down: [down.zpos], " + grid_desc += "Right: [right.zpos], " + grid_desc += "Left: [left.zpos]" + else + our_spot = our_spot.ChangeTurf(/turf/simulated/floor/fakespace) + our_spot.desc = grid_desc + + +#undef Z_LEVEL_NORTH +#undef Z_LEVEL_SOUTH +#undef Z_LEVEL_EAST +#undef Z_LEVEL_WEST diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm new file mode 100644 index 00000000000..8f83c0ab5e4 --- /dev/null +++ b/code/modules/space_management/zlevel_manager.dm @@ -0,0 +1,131 @@ +var/global/datum/zlev_manager/space_manager = new + +/datum/zlev_manager + // A list of z-levels + var/list/z_list = list() + var/list/heaps = list() + + var/datum/spacewalk_grid/linkage_map + +// Populate our space level list +// and prepare space transitions +/datum/zlev_manager/proc/initialize() + var/num_official_z_levels = map_transition_config.len + var/k = 1 + + // First take care of "Official" z levels, without visiting levels outside of the list + for(var/A in map_transition_config) + // `A` is the name + // `map_transition_config[A]` is the transition type + z_list["[k]"] = new /datum/space_level(k, A, transition_type = map_transition_config[A]) + if(k > world.maxz) + CRASH("More map transitions defined than existent z levels - [num_official_z_levels]") + k++ + + // Then, we take care of unmanaged z levels + // They get the default linkage of SELFLOOPING + for(var/i = k, i <= world.maxz, i++) + z_list["[i]"] = new /datum/space_level(i) + + +/datum/zlev_manager/proc/get_zlev(z) + if(!("[z]" in z_list)) + throw EXCEPTION("Unmanaged z level: '[z]'") + else + return z_list["[z]"] + +/* +* "Dirt" management +* "Dirt" is used to keep track of whether a z level should automatically have +* stuff on it initialize or not - If you're loading a map, place +* a freeze on the z levels it touches so as to prevent atmos from exploding, +* among other things +*/ + + +// Returns whether the given z level has a freeze on initialization +/datum/zlev_manager/proc/is_zlevel_dirty(z) + var/datum/space_level/our_z = get_zlev(z) + return (our_z.dirt_count > 0) + + +// Increases the dirt count on a z level +/datum/zlev_manager/proc/add_dirt(z) + var/datum/space_level/our_z = get_zlev(z) + if(our_z.dirt_count == 0) + log_debug("Placing an init freeze on z-level '[our_z.zpos]'!") + our_z.dirt_count++ + + +// Decreases the dirt count on a z level +/datum/zlev_manager/proc/remove_dirt(z) + var/datum/space_level/our_z = get_zlev(z) + our_z.dirt_count-- + if(our_z.dirt_count == 0) + our_z.resume_init() + if(our_z.dirt_count < 0) + log_debug("WARNING: Imbalanced dirt removal") + our_z.dirt_count = 0 + +/datum/zlev_manager/proc/postpone_init(z, thing) + var/datum/space_level/our_z = get_zlev(z) + our_z.init_list.Add(thing) + + +/** +* +* SPACE ALLOCATION +* +*/ + + +// For when you need the z-level to be at a certain point +/datum/zlev_manager/proc/increase_max_zlevel_to(new_maxz) + if(world.maxz>=new_maxz) + return + while(world.maxznew_maxz) + kill_topmost_zlevel() + +// Decrements the max z-level by one +// not normally used, but hey the swapmap loader wanted it +/datum/zlev_manager/proc/kill_topmost_zlevel() + var/our_z = world.maxz + var/datum/space_level/S = get_zlev(our_z) + z_list.Remove(S) + qdel(S) + world.maxz-- + + +// An internally-used proc used for heap-zlevel management +/datum/zlev_manager/proc/add_new_heap() + world.maxz++ + var/our_z = world.maxz + var/datum/space_level/yup = new /datum/space_level/heap(our_z) + z_list["[our_z]"] = yup + return yup + +// This is what you can call to allocate a section of space +// Later, I'll add an argument to let you define the flags on the region +/datum/zlev_manager/proc/allocate_space(width, height) + if(!heaps.len) + heaps.len++ + heaps[heaps.len] = add_new_heap() + var/datum/space_level/heap/our_heap + for(our_heap in heaps) + var/weve_got_vacancy = our_heap.request(width, height) + if(weve_got_vacancy) + break // We're sticking with the present value of `our_heap` - it's got room diff --git a/code/modules/space_transition/space_transition.dm b/code/modules/space_transition/space_transition.dm deleted file mode 100644 index fe63154b017..00000000000 --- a/code/modules/space_transition/space_transition.dm +++ /dev/null @@ -1,187 +0,0 @@ -//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube - -#define Z_LEVEL_NORTH "1" -#define Z_LEVEL_SOUTH "2" -#define Z_LEVEL_EAST "4" -#define Z_LEVEL_WEST "8" - - -var/list/z_levels_list = list() - -/datum/space_level - var/name = "Your config settings failed, you need to fix this for the datum space levels to work" - var/list/neigbours - var/z_value = 1 //actual z placement - var/linked = 1 - var/xi - var/yi //imaginary placements on the grid - -/datum/space_level/New() - neigbours = list() - var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST) - for(var/A in L) - neigbours[A] = src - -/datum/space_level/proc/set_neigbours(list/L) - for(var/datum/point/P in L) - if(P.x == xi) - if(P.y == yi+1) - neigbours[Z_LEVEL_NORTH] = P.spl - P.spl.neigbours[Z_LEVEL_SOUTH] = src - else if(P.y == yi-1) - neigbours[Z_LEVEL_SOUTH] = P.spl - P.spl.neigbours[Z_LEVEL_NORTH] = src - else if(P.y == yi) - if(P.x == xi+1) - neigbours[Z_LEVEL_EAST] = P.spl - P.spl.neigbours[Z_LEVEL_WEST] = src - else if(P.x == xi-1) - neigbours[Z_LEVEL_WEST] = P.spl - P.spl.neigbours[Z_LEVEL_EAST] = src - -/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else - var/list/neigbours = list() - var/x - var/y - var/datum/space_level/spl - -/datum/point/New(nx, ny, list/point_grid) - if(!point_grid) - qdel(src) - return - var/list/L = point_grid[1] - if(nx > point_grid.len || ny > L.len) - qdel(src) - return - x = nx - y = ny - if(point_grid[x][y]) - return - point_grid[x][y] = src - -/datum/point/proc/set_neigbours(list/grid) - var/max_X = grid.len - var/list/max_Y = grid[1] - max_Y = max_Y.len - neigbours.Cut() - if(x+1 <= max_X) - neigbours |= grid[x+1][y] - if(x-1 >= 1) - neigbours |= grid[x-1][y] - if(y+1 <= max_Y) - neigbours |= grid[x][y+1] - if(y-1 >= 1) - neigbours |= grid[x][y-1] - - -//config/space_levels.txt is where you define your zlevel datum names, their connection to actual z levels and if you want them connected to one another or not -//Grammar: Name;z value;linked/unlinked -//Name is the name of the datum, just for the sake of it -//z value is to what actual map z level this datum is pointing -//linked/unlinked decide if you want the z level in the general map or not, for example centcomm is not reachable -//Each entry must be separated with a single empty line, no spaces outside the name -//No comments in the file allowed - -/proc/setup_map_transitions() //listamania - var/list/SLS = file2list("config/space_levels.txt", "\n\n") - var/datum/space_level/D - var/list/config_settings[SLS.len][] - for(var/A in SLS) - config_settings[SLS.Find(A)] = splittext(A, ";") - var/conf_set_len = SLS.len - SLS.Cut() - for(var/A in config_settings) - D = new() - D.name = A[1] - D.z_value = text2num(A[2]) - if(A[3] != "linked") - D.linked = 0 - z_levels_list["[D.z_value]"] = D - else - SLS.Add(D) - var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1] - var/list/grid = list() - var/datum/point/P - for(var/i = 1, i<=conf_set_len*2+1, i++) - for(var/j = 1, j<=conf_set_len*2+1, j++) - P = new/datum/point(i,j, point_grid) - point_grid[i][j] = P - grid.Add(P) - for(var/datum/point/pnt in grid) - pnt.set_neigbours(point_grid) - P = point_grid[conf_set_len][conf_set_len] - var/list/possible_points = list() - var/list/used_points = list() - grid.Cut() - while(SLS.len) - D = pick(SLS) - SLS.Remove(D) - D.xi = P.x - D.yi = P.y - P.spl = D - possible_points |= P.neigbours - used_points |= P - possible_points.Remove(used_points) - D.set_neigbours(used_points) - P = pick(possible_points) - grid["[D.z_value]"] = D - - for(var/A in z_levels_list) - grid[A] = z_levels_list[A] - - for(var/turf/space/S in world) //Define the transistions of the z levels - if(S.x <= TRANSITIONEDGE) - D = grid["[S.z]"] - if(D.neigbours[Z_LEVEL_WEST] != D) - D = D.neigbours[Z_LEVEL_WEST] - S.destination_z = D.z_value - else - while(D.neigbours[Z_LEVEL_EAST] != D) - D = D.neigbours[Z_LEVEL_EAST] - S.destination_z = D.z_value - S.destination_x = world.maxx - TRANSITIONEDGE - 2 - S.destination_y = S.y - - if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) - D = grid["[S.z]"] - if(D.neigbours[Z_LEVEL_EAST] != D) - D = D.neigbours[Z_LEVEL_EAST] - S.destination_z = D.z_value - else - while(D.neigbours[Z_LEVEL_WEST] != D) - D = D.neigbours[Z_LEVEL_WEST] - S.destination_z = D.z_value - S.destination_x = TRANSITIONEDGE + 2 - S.destination_y = S.y - - if(S.y <= TRANSITIONEDGE) - D = grid["[S.z]"] - if(D.neigbours[Z_LEVEL_SOUTH] != D) - D = D.neigbours[Z_LEVEL_SOUTH] - S.destination_z = D.z_value - else - while(D.neigbours[Z_LEVEL_NORTH] != D) - D = D.neigbours[Z_LEVEL_NORTH] - S.destination_z = D.z_value - S.destination_x = S.x - S.destination_y = world.maxy - TRANSITIONEDGE - 2 - - if(S.y >= (world.maxy - TRANSITIONEDGE - 1)) - D = grid["[S.z]"] - if(D.neigbours[Z_LEVEL_NORTH] != D) - D = D.neigbours[Z_LEVEL_NORTH] - S.destination_z = D.z_value - else - while(D.neigbours[Z_LEVEL_SOUTH] != D) - D = D.neigbours[Z_LEVEL_SOUTH] - S.destination_z = D.z_value - S.destination_x = S.x - S.destination_y = TRANSITIONEDGE + 2 - - for(var/A in grid) - z_levels_list[A] = grid[A] - -#undef Z_LEVEL_NORTH -#undef Z_LEVEL_SOUTH -#undef Z_LEVEL_EAST -#undef Z_LEVEL_WEST diff --git a/code/modules/spacial_allocator/zlevel.dm b/code/modules/spacial_allocator/zlevel.dm deleted file mode 100644 index 8b8bec70b87..00000000000 --- a/code/modules/spacial_allocator/zlevel.dm +++ /dev/null @@ -1,73 +0,0 @@ -/datum/zlevel - var/flags = 0 - var/dirt_count = 0 - var/zpos - var/list/init_list = list() - -/datum/zlevel/New(z) - zpos = z - -/datum/zlevel/proc/resume_init() - if(dirt_count > 0) - throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'") - log_debug("Releasing freeze on z-level '[zpos]'!") - log_debug("Beginning initialization!") - var/list/our_atoms = init_list // OURS NOW!!! (Keeping this list to ourselves will prevent hijack) - init_list = list() - var/list/late_maps = list() - var/list/pipes = list() - var/list/cables = list() - var/watch = start_watch() - for(var/schmoo in our_atoms) - var/atom/movable/AM = schmoo - if(AM) // to catch stuff like the nuke disk that no longer exists - - // This can mess with our state - we leave these for last - if(istype(AM, /obj/effect/landmark/map_loader)) - late_maps.Add(AM) - continue - AM.initialize() - if(istype(AM, /obj/machinery/atmospherics)) - pipes.Add(AM) - else if(istype(AM, /obj/structure/cable)) - cables.Add(AM) - log_debug("Primary initialization finished in [stop_watch(watch)]s.") - our_atoms.Cut() - if(pipes.len) - do_pipes(pipes) - if(cables.len) - do_cables(cables) - if(late_maps.len) - do_late_maps(late_maps) - -/datum/zlevel/proc/do_pipes(list/pipes) - var/watch = start_watch() - log_debug("Building pipenets on z-level '[zpos]'!") - for(var/schmoo in pipes) - var/obj/machinery/atmospherics/machine = schmoo - if(machine) - machine.build_network() - pipes.Cut() - log_debug("Took [stop_watch(watch)]s") - -/datum/zlevel/proc/do_cables(list/cables) - var/watch = start_watch() - log_debug("Building powernets on z-level '[zpos]'!") - for(var/schmoo in cables) - var/obj/structure/cable/C = schmoo - if(C) - makepowernet_for(C) - cables.Cut() - log_debug("Took [stop_watch(watch)]s") - -/datum/zlevel/proc/do_late_maps(list/late_maps) - var/watch = start_watch() - log_debug("Loading map templates on z-level '[zpos]'!") - zlevels.add_dirt(zpos) // Let's not repeatedly resume init for each template - for(var/schmoo in late_maps) - var/obj/effect/landmark/map_loader/ML = schmoo - if(ML) - ML.initialize() - late_maps.Cut() - zlevels.remove_dirt(zpos) - log_debug("Took [stop_watch(watch)]s") diff --git a/code/modules/spacial_allocator/zlevel_manager.dm b/code/modules/spacial_allocator/zlevel_manager.dm deleted file mode 100644 index 3c6fb0a0048..00000000000 --- a/code/modules/spacial_allocator/zlevel_manager.dm +++ /dev/null @@ -1,89 +0,0 @@ -var/global/datum/zlev_manager/zlevels = new - -/datum/zlev_manager - // A list of z-levels - var/list/z_list = list() - - -// Populate our z level list -/datum/zlev_manager/proc/initialize() - z_list.len = world.maxz - for(var/i = 1, i <= world.maxz, i++) - z_list[i] = new /datum/zlevel(i) - - - -/datum/zlev_manager/proc/get_zlev(z) - if(z < 1) - throw EXCEPTION("Non-positive z level given!") - else if(z > z_list.len) - throw EXCEPTION("Untracked z level: '[z]'") - else - return z_list[z] - -// For when you need the z-level to be at a certain point -/datum/zlev_manager/proc/increase_max_zlevel_to(new_maxz) - if(world.maxz>=new_maxz) - return - while(world.maxznew_maxz) - kill_topmost_zlevel() - -// Decrements the max z-level by one -// not normally used, but hey the swapmap loader wanted it -/datum/zlev_manager/proc/kill_topmost_zlevel() - var/our_z = world.maxz - qdel(z_list[our_z]) - z_list.len-- - world.maxz-- - -/* -* "Dirt" management -* "Dirt" is used to keep track of whether a z level should automatically have -* stuff on it initialize or not - the map loaders, when set to defer init, place -* a freeze on the z levels they touch so as to prevent atmos from exploding, -* among other things -*/ - - -// Returns whether the given z level has a freeze on initialization -/datum/zlev_manager/proc/is_zlevel_dirty(z) - var/datum/zlevel/our_z = get_zlev(z) - return (our_z.dirt_count > 0) - - -// Increases the dirt count on a z level -/datum/zlev_manager/proc/add_dirt(z) - var/datum/zlevel/our_z = get_zlev(z) - if(our_z.dirt_count == 0) - log_debug("Placing an init freeze on z-level '[our_z.zpos]'!") - our_z.dirt_count++ - - -// Decreases the dirt count on a z level -/datum/zlev_manager/proc/remove_dirt(z) - var/datum/zlevel/our_z = get_zlev(z) - our_z.dirt_count-- - if(our_z.dirt_count == 0) - our_z.resume_init() - if(our_z.dirt_count < 0) - log_debug("WARNING: Imbalanced dirt removal") - our_z.dirt_count = 0 - -/datum/zlev_manager/proc/postpone_init(z, thing) - var/datum/zlevel/our_z = get_zlev(z) - our_z.init_list.Add(thing) diff --git a/code/modules/store/store.dm b/code/modules/store/store.dm index f0199089704..7d5fc1e527d 100644 --- a/code/modules/store/store.dm +++ b/code/modules/store/store.dm @@ -48,6 +48,7 @@ var/global/datum/store/centcomm_store=new /datum/store/proc/reconnect_database() for(var/obj/machinery/computer/account_database/DB in world) + // TODO: Tie into space manager if((DB.z in config.station_levels)) linked_db = DB break @@ -62,4 +63,4 @@ var/global/datum/store/centcomm_store=new return 0 // Give them the item. item.deliver(usr) - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 5e49a97fc59..b49ccc6a838 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -343,3 +343,32 @@ I use this so that this can be made better once the organ overhaul rolls out -- if(!istype(owner)) // You're not the primary organ of ANYTHING, bucko return 0 return src == O.get_int_organ(organ_tag) + +/obj/item/organ/serialize() + var/data = ..() + if(status != 0) + data["status"] = status + if(robotic > 0) + data["robotic"] = robotic + + // Save the DNA datum if: The owner doesn't exist, or the dna doesn't match + // the owner + if(!(owner && dna.unique_enzymes == owner.dna.unique_enzymes)) + data["dna"] = dna.serialize() + return data + +/obj/item/organ/deserialize(var/data) + switch(data["robotic"]) + if(1) + mechassist() + if(2) + robotize() + else + // Nothing + if(isnum(data["status"])) + status = data["status"] + if(islist(data["dna"])) + // The only thing the official proc does is + //instantiate the list and call this proc + dna.deserialize(data["dna"]) + ..() diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 10d7fe724ea..1c3f05f5816 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -836,12 +836,7 @@ Note that amputating the affected organ does in fact remove the infection from t ..() if(company && istext(company)) - model = company - var/datum/robolimb/R = all_robolimbs[company] - if(R) - force_icon = R.icon - name = "[R.company] [initial(name)]" - desc = "[R.desc]" + set_company(company) cannot_break = 1 get_icon() @@ -849,6 +844,16 @@ Note that amputating the affected organ does in fact remove the infection from t if(T) T.robotize() + + +/obj/item/organ/external/proc/set_company(var/company) + model = company + var/datum/robolimb/R = all_robolimbs[company] + if(R) + force_icon = R.icon + name = "[R.company] [initial(name)]" + desc = "[R.desc]" + /obj/item/organ/external/proc/mutate() src.status |= ORGAN_MUTATED if(owner) owner.update_body() @@ -969,3 +974,19 @@ Note that amputating the affected organ does in fact remove the infection from t continue wounds -= W qdel(W) + + +/obj/item/organ/external/serialize() + var/list/data = ..() + if(robotic == 2) + data["company"] = model + // If we wanted to store wound information, here is where it would go + return data + +/obj/item/organ/external/deserialize(list/data) + var/company = data["company"] + if(company && istext(company)) + set_company(company) + ..() // Parent call loads in the DNA + if(data["dna"]) + sync_colour_to_dna() diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm index f226edc08eb..8b86a3082d8 100644 --- a/code/modules/telesci/bscrystal.dm +++ b/code/modules/telesci/bscrystal.dm @@ -22,6 +22,7 @@ qdel(src) /obj/item/weapon/ore/bluespace_crystal/proc/blink_mob(var/mob/living/L) + // TODO: Tie into space manager if(L.z in config.admin_levels) src.visible_message("[src]'s fragments begin rapidly vibrating and blink out of existence.") qdel(src) @@ -33,6 +34,10 @@ if(isliving(hit_atom)) blink_mob(hit_atom) qdel(src) +// Blueapce crystal fragments (stops point farming) +/obj/item/weapon/ore/bluespace_crystal/fragment + points = 0 + refined_type = null // Artifical bluespace crystal, doesn't give you much research. /obj/item/weapon/ore/bluespace_crystal/artificial @@ -45,7 +50,7 @@ // Polycrystals, aka stacks -var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/stack_recipe("Breadkdown into bluespace crystal", /obj/item/weapon/ore/bluespace_crystal, 1, one_per_turf = 0, on_floor = 1)) +var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/stack_recipe("Breakdown into bluespace crystal", /obj/item/weapon/ore/bluespace_crystal/fragment, 1, one_per_turf = 0, on_floor = 1)) /obj/item/stack/sheet/bluespace_crystal name = "bluespace polycrystal" @@ -59,4 +64,4 @@ var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/st ..() recipes = bluespace_crystal_recipes pixel_x = rand(0,4)-4 - pixel_y = rand(0,4)-4 \ No newline at end of file + pixel_y = rand(0,4)-4 diff --git a/code/world.dm b/code/world.dm index c82b00b8e9a..508591604f0 100644 --- a/code/world.dm +++ b/code/world.dm @@ -20,6 +20,8 @@ var/global/datum/global_init/init = new () #define RECOMMENDED_VERSION 510 +var/global/list/map_transition_config = MAP_TRANSITION_CONFIG + /world/New() //logs var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") @@ -51,7 +53,7 @@ var/global/datum/global_init/init = new () // Create robolimbs for chargen. populate_robolimb_list() - setup_map_transitions() //Before the MC starts up + space_manager.initialize() //Before the MC starts up processScheduler = new master_controller = new /datum/controller/game_controller() diff --git a/config/example/config.txt b/config/example/config.txt index 2f723c704f4..eb44c6d828a 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -324,3 +324,8 @@ DISABLE_SPACE_RUINS ## How many loadout points players may spend in character setup #MAX_LOADOUT_POINTS 5 + +# How many minutes players must wait, from round start, before they can ghost out +# and still qualify for re-entering the round. Defaults to 30. +# Setting this to 0 will disable the penalty period +#ROUND_ABANDON_PENALTY_PERIOD 30 diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css index 3829cbd3f48..e299fa5a5c5 100644 --- a/goon/browserassets/css/browserOutput.css +++ b/goon/browserassets/css/browserOutput.css @@ -245,8 +245,8 @@ em {font-style: normal; font-weight: bold;} .deptradio {color: #993399;} .comradio {color: #193A7A;} .syndradio {color: #6d3f40;} -.dsquadradio {color: #686868;} -.resteamradio {color: #18BC46;} +.dsquadradio {color: #686868;} +.resteamradio {color: #18BC46;} .airadio {color: #FF00FF;} .centradio {color: #5C5C8A;} .secradio {color: #A30000;} @@ -255,17 +255,17 @@ em {font-style: normal; font-weight: bold;} .sciradio {color: #993399;} .supradio {color: #5F4519;} .srvradio {color: #6eaa2c;} -.admin_channel {color: #9A04D1; font-weight: bold;} -.mod_channel {color: #402A14; font-weight: bold;} -.mod_channel_admin {color: #402A14; font-weight: bold;} +.admin_channel {color: #9A04D1; font-weight: bold;} +.mod_channel {color: #402A14; font-weight: bold;} +.mod_channel_admin {color: #402A14; font-weight: bold;} .djradio {color: #663300;} -.binaryradio {color: #0B0050; font-family: 'Courier New', Courier, monospace;} +.binaryradio {color: #0B0050; font-family: 'Courier New', Courier, monospace;} .mommiradio {color: navy;} .alert {color: #ff0000;} -h1.alert, h2.alert {color: #000000;} +h1.alert, h2.alert {color: #000000;} .ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;} .emote { font-style: italic;} -.selecteddna {color: #FFFFFF; background-color: #001B1B} +.selecteddna {color: #FFFFFF; background-color: #001B1B} .attack {color: #ff0000;} .moderate {color: #CC0000;} @@ -276,20 +276,20 @@ h1.alert, h2.alert {color: #000000;} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} .danger {color: #ff0000; font-weight: bold;} .userdanger {color: #ff0000; font-weight: bold; font-size: 120%;} -.biggerdanger {color: #ff0000; font-weight: bold; font-size: 150%;} +.biggerdanger {color: #ff0000; font-weight: bold; font-size: 150%;} .info {color: #0000CC;} .notice {color: #000099;} .bnotice {color: #000099; font-weight: bold;} -.boldnotice {color: #000099; font-weight: bold;} +.boldnotice {color: #000099; font-weight: bold;} .suicide {color: #ff5050; font-style: italic;} - +.green {color: #03bb39;} .announce {color: #228b22; font-weight: bold;} -.boldannounce {color: #ff0000; font-weight: bold;} -.greenannounce {color: #00ff00; font-weight: bold;} +.boldannounce {color: #ff0000; font-weight: bold;} +.greenannounce {color: #00ff00; font-weight: bold;} .alien {color: #543354;} -.noticealien {color: #00c000;} +.noticealien {color: #00c000;} .alertalien {color: #00c000; font-weight: bold;} .sinister {color: #800080; font-weight: bold; font-style: italic;} /* /vg/ */ @@ -334,12 +334,12 @@ h1.alert, h2.alert {color: #000000;} .orangei {color: #ffa500; font-style: italic;} .orangeb {color: #ffa500; font-weight: bold;} -.revennotice {color: #1d2953;} -.revenboldnotice {color: #1d2953; font-weight: bold;} -.revenbignotice {color: #1d2953; font-weight: bold; font-size: 3;} +.revennotice {color: #1d2953;} +.revenboldnotice {color: #1d2953; font-weight: bold;} +.revenbignotice {color: #1d2953; font-weight: bold; font-size: 3;} .revenminor {color: #823abb} -.revenwarning {color: #760fbb; font-style: italic;} -.revendanger {color: #760fbb; font-weight: bold; font-size: 3;} +.revenwarning {color: #760fbb; font-style: italic;} +.revendanger {color: #760fbb; font-weight: bold; font-size: 3;} /* /vg/ */ .good {color: green;} diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm index b0aad73286d..66bbc5fad86 100644 --- a/goon/code/datums/browserOutput.dm +++ b/goon/code/datums/browserOutput.dm @@ -171,7 +171,8 @@ var/list/chatResources = list( var/list/partial = splittext(iconData, "{") return replacetext(copytext(partial[2], 3, -5), "\n", "") -/proc/bicon(var/obj) +/proc/bicon(var/obj, var/use_class = 1) + var/class = use_class ? "class='icon misc'" : null if (!obj) return @@ -179,7 +180,7 @@ var/list/chatResources = list( if (!bicon_cache["\ref[obj]"]) // Doesn't exist yet, make it. bicon_cache["\ref[obj]"] = icon2base64(obj) - return "" + return "" // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with. var/atom/A = obj @@ -191,12 +192,10 @@ var/list/chatResources = list( I = icon() I.Insert(temp, dir = SOUTH) bicon_cache[key] = icon2base64(I, key) + if(use_class) + class = "class='icon [A.icon_state]'" - return "" - -//Aliases for bicon -/proc/bi(obj) - bicon(obj) + return "" var/to_chat_filename var/to_chat_line diff --git a/html/changelog.html b/html/changelog.html index 27fe9b5f57f..5214279f440 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,297 @@ -->
    +

    08 August 2016

    +

    Ar3nn updated:

    +
      +
    • Telekinesis no longer is subject to meatspace problems
    • +
    +

    Chakirski updated:

    +
      +
    • Added animal AI holograms.
    • +
    • .45 Magazine sprites for the M1911 are now longer invisible.
    • +
    • Hoodies no longer look like labcoats while in hand.
    • +
    • Ectoplasm spawns in cult mining rooms instead of an invisible "weapon".
    • +
    • Duffel bag descriptions and names no longer contain "duffle".
    • +
    • Syndicate medical duffel bags can now be seen while in hand.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Adds a "Save" buildmode for admins to preserve their creations for later. This is currently in an early stage, so don't be surprised by errors!
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Holy Water will no longer make you stutter for ages if you're not a cultist
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Orion Ship message being unheard when held in-hand
    • +
    • Adds headphones into the game as a loadout item
    • +
    • Removes fireproof core malf AI power
    • +
    • upgrade turrets malf AI power CPU reduced from 50 to to 30
    • +
    • Overload machine cost increased from 15 to 20
    • +
    • Override machine cost increased from 15 to 30
    • +
    • can override/overload field generators again
    • +
    • Machine uprisers will slowly die if they aren't attacking someone
    • +
    • Adds in Hostile lockdown malf AI power for 30 CPU
    • +
    • Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively
    • +
    • AI's no longer have flood mode on air alarms by default
    • +
    • Adds in lip reading malf AI power for 30 CPU
    • +
    • Allows accessories to hypothetically grant armor to their wearer
    • +
    • Greytide spear illusions actually have an attack sound now
    • +
    • fixes the wormhole event being much shorter than intended
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Walls now melt when hot
    • +
    • Added actual coated rwalls - you can make them by clicking on an existing rwall with at least 2 plasteel in hand. Has infinite temp resistance.
    • +
    • Replaced all fake coated rwalls with new rwalls in both metastation (where they should be) and boxstation
    • +
    • Bandaging someone no longer stabs your eyes with bright green
    • +
    • Fixed repainted-to-wood metal flooring in courtroom - it's now actually wood
    • +
    • Fixed windoor in witness stand facing the wrong way
    • +
    +

    KasparoVy updated:

    +
      +
    • Traitors with the Maroon objective will no longer succeed if their target is in a locker on the shuttle.
    • +
    • Traitors with the Assassination objective will no longer fail if their target is assassinated/borged/debrained but on a Z-level greater than the derelict.
    • +
    +

    Krausus updated:

    +
      +
    • Fire will now totally consume you, rather than timidly hiding under your clothes.
    • +
    • Admin freeze overlays should no longer disappear from humans until they're actually unfrozen.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • Adds cheap sunglasses. They provide no flash protection, but are available in the loadout and clothesmate.
    • +
    +

    Pinatacolada updated:

    +
      +
    • Makes the swedish gene spit out weird swedish chars and sounds
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes "is too cumbersome to carry in one hand" from showing up to other players.
    • +
    +

    Yurivw updated:

    +
      +
    • Condimaster now actually makes bottles. Removed: Unused options in admin secret menu are now removed.
    • +
    +

    chopchop1614 updated:

    +
      +
    • fix bluespace crystals exploit
    • +
    + +

    03 August 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes a rare case where the singularity would escape containment when properly set up+contained
    • +
    +

    Krausus updated:

    +
      +
    • Non-respawnable ghosts will no longer qualify for mid-round rejoining (event antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this.
    • +
    • Cryodorms will no longer produce respawnable ghosts for the first 30 minutes of the round.
    • +
    • Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above their cryo pod, in the spooky cryodorms.
    • +
    • Cryodorms will now despawn you 90% faster if you willingly enter one.
    • +
    • Suiciding in the first 30 minutes of a round will no longer allow you to ghost and be respawnable.
    • +
    • Becoming a non-respawnable ghost lasts the entire round, even if you ghost in a respawnable manner later on.
    • +
    • You can no longer spam pinging posibrains, and cannot ping them at all if you cannot volunteer for one.
    • +
    • Missing limbs will now be grayed out on your health doll.
    • +
    +

    chopchop1614 updated:

    +
      +
    • Fixed the C4 labcoat exploding bug
    • +
    + +

    01 August 2016

    +

    Crazylemon64 updated:

    +
      +
    • Admins are now able to print a map of the z levels.
    • +
    • Admins are now capable of scrambling the z levels' transitions.
    • +
    • Janiborg trash bags no longer fit down disposals when empty
    • +
    +

    Fethas updated:

    +
      +
    • (Maybe?)..We actually check if the race HAS BLOOD before trying to suck them
    • +
    • Due to various complaints from tajarans having hand cramps, glove makers have removed plasteel from the fabric.
    • +
    • Plasmaman can no longer be vampires.
    • +
    • Removes the mask check on both victim AND vampire, also makes the message a bit more obscure, so it's up to your imagination of where you are biting them and with what.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Medical stacks now have 6 uses
    • +
    • Medical stacks now heal 25 burn/brute
    • +
    • Applying a medical stack to others is instant, no matter what
    • +
    • Applying any medical stack to yourself has a 2 second delay
    • +
    • Applying a splint to yourself has a 10 second delay
    • +
    • No more RNG fumbling of putting splints to yourself
    • +
    • Confirmation for applying medical stacks is now green
    • +
    • Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, 1 roll of gauze, and medipen.
    • +
    • Amount of splints in medical vendors increased from 2 to 4
    • +
    • Fixes weird icon updates when getting healed by medical kits
    • +
    • Adds in object burning system that allows things to be lit on fire
    • +
    • being on fire should heat you up a bit quicker and do a bit more damage
    • +
    • Novaflowers ignite you rather than uselessly heating you up
    • +
    • Adjusts a few pyrotechnic chems to better fit with other tweaks to fire damage
    • +
    +

    IcyV updated:

    +
      +
    • Adds a unique axe for Atmos-traitors
    • +
    +

    Krausus updated:

    +
      +
    • Probably fixed some very specific items messing up View Variables for no adequately explicable reason.
    • +
    • Fixed round-end antagonist report failing to print due to null objectives.
    • +
    +

    Kyep updated:

    +
      +
    • Added atmos grenade kit to traitor uplink.
    • +
    • Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes #5232
    • +
    +

    TheBeoni updated:

    +
      +
    • Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security one Added picture because i do not like that red label
    • +
    +

    TheDZD updated:

    +
      +
    • Shadowling ascendance and badmins pressing the "Destroy All Lights" button should no longer bring the server to its knees.
    • +
    • Broken lights will no longer re-break.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Using ATMs leaves fingerprints behind
    • +
    +

    Twinmold updated:

    +
      +
    • Nuke Ops airtank connected to pipenet now.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Readded colored cable-cuffs.
    • +
    • Making stacks of metal rods now updates the icon correctly.
    • +
    + +

    28 July 2016

    +

    A Giant-Ass Mountain of Salt updated:

    +
      +
    • Re-adds PDA slot.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Adds an explosion buildmode
    • +
    • "Drop Everything" in VV no longer causes limbs to fall to the ground.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • IAAs can now select the classic secHUD in loadouts
    • +
    • adds bananas and suit jackets to the loadout system
    • +
    • adds dress shoes and fancy sandals to the loadout system
    • +
    • Miners can now get the mining coat from loadouts
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes organ repair surgery saying an organ wasn't damaged when it actually was
    • +
    • Removes the 1 burn heal from regular ointment
    • +
    • Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)
    • +
    • Fixes a few crafting recipes not having the proper category
    • +
    • Fixes laser slugs not firing lasers
    • +
    • Adjusts the damage/consistency of improvised slugs
    • +
    • Adds in craftable bolas; throw them at someone to slow them down
    • +
    • Secvend starts off with e-bolas
    • +
    • Can make spears with personal crafting now
    • +
    • Fixes teacups and some other drinks having no sprite, in-hand, or object
    • +
    • adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies
    • +
    • Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand
    • +
    • Fixes cablecuffs not having a unique in-hand icon
    • +
    • Fixes cable coils not having a unique in-hand icon
    • +
    • All cablecuffs will be red, regardless of what they're produced from
    • +
    • Fixes an unlimited metal exploit
    • +
    • IV Drip sprites updated; has visual feedback for if it's injecting or taking blood
    • +
    • IV Drip injection rate dramatically increased
    • +
    • Warning ping for when someone is low on blood
    • +
    • Support for species with exotic blood type
    • +
    • Alt-Click to toggle between modes
    • +
    • Sensory restoration virology symptom no longer has anti-stun properties nor heals brain damage, but has a lower acquisition level
    • +
    • Damage convert heals individual limbs instead of healing overall damage (actual impact is low)
    • +
    • Librarian now starts off with a bookbag
    • +
    • Bookbag can now hold Bibles, cult tomes, books, and spellbooks
    • +
    • Can empty a bookbag into a bookshelf
    • +
    • Fixes an exploit where you could generate wood out of thin air
    • +
    • Fixes blobspores doing more damage than intended
    • +
    +

    Fox-McCloud updated:

    +
      +
    • Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws
    • +
    • Fixes some personal crafting behaving as other than intended
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Fixed brig cell block APCs not getting power
    • +
    • Fixed space buggery Kyet made :angry:
    • +
    • Fixed missing light near labor shuttle dock
    • +
    • Fixed wrongly placed cobweb in solitary
    • +
    • Fixed basketball court not having a basketball
    • +
    • Added windows to brig processing entrance
    • +
    • Re-added the missing EOD and biohazard lockers in Armory
    • +
    • 6 gas masks from Armory
    • +
    • Added grid check into random events.
    • +
    +

    Krausus updated:

    +
      +
    • The voting panel now uses the browser datum, which means it looks nicer.
    • +
    • The voting panel now updates while a vote is in progress.
    • +
    • When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in "vote".
    • +
    • Custom votes will now show full voting results upon completion.
    • +
    • Admins should no longer lose the "cancel vote" link in the voting panel.
    • +
    • View Variables should probably stop crashing admins.
    • +
    • The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen.
    • +
    • Admins now have click shortcuts for opening a player panel, showing mob info, and viewing variables. Specifics are in Hotkey Help.
    • +
    +

    Kyep updated:

    +
      +
    • Admins can now see attacks against SSD players more easily.
    • +
    • Clarified the text you get when examining a SSD player.
    • +
    • It is now possible for admins to remove a person's vamp thrall status.
    • +
    • Adds Vox, Greytide & Soviet loadouts to admin Select Equipment verb.
    • +
    • Fixes an issue with spy loadouts, and excessive access on loadouts in general
    • +
    +

    Spacemanspark updated:

    +
      +
    • Cardboard boxes now have their own specific name in the cardboard sheets menu.
    • +
    +

    TheDZD updated:

    +
      +
    • Fixes tempgun not recharging.
    • +
    • Fixes tempgun beams costing one tenth of what they are supposed to.
    • +
    • Admin-only jobs check for R_EVENT now, instead of R_ADMIN, as event-related tools should.
    • +
    • Mentors should no longer get spammed by the library checkout computer on occasion.
    • +
    • Mentors should no longer get spammed by mirrors due to body accessories.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • AI Integrity Restorers now destroy any AIs inside if they get EMP'd
    • +
    • AI Integrity Restorers can be deconstructed if broken via explosions. This kills the AI inside
    • +
    +

    Twinmold updated:

    +
      +
    • Can no longer destroy pods with anything other than brute and burn weapons.
    • +
    • Can no longer pull someone out of a pod when no one is actually in the pod.
    • +
    • Can now melee attack pods with weapons when harm intent is on.
    • +
    • Vox Objective 4 now calculates the kills vox raiders actually have, instead of always complete.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Gives Combat Gloves to Code Red ERT agents.
    • +
    • Gives Code Gamma Engineering ERT agents Combat Gloves.
    • +
    +

    monster860, clusterfack, and DeityLink updated:

    +
      +
    • Adds space parallax
    • +
    +

    tigercat2000 updated:

    +
      +
    • Removes space parallax, due to server overhead, input lag & bugs
    • +
    +

    21 July 2016

    Alffd updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 1309d5211dd..49c48046292 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2433,3 +2433,252 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. and Xenomorph Larva Whack-A-Mole monster860: - bugfix: Brig timer UI reopening after being closed fixed. +2016-07-28: + A Giant-Ass Mountain of Salt: + - rscadd: Re-adds PDA slot. + Crazylemon64: + - rscadd: Adds an explosion buildmode + - bugfix: '"Drop Everything" in VV no longer causes limbs to fall to the ground.' + FlattestGuitar: + - tweak: IAAs can now select the classic secHUD in loadouts + - rscadd: adds bananas and suit jackets to the loadout system + - rscadd: adds dress shoes and fancy sandals to the loadout system + - bugfix: Miners can now get the mining coat from loadouts + Fox McCloud: + - bugfix: Fixes organ repair surgery saying an organ wasn't damaged when it actually + was + - tweak: Removes the 1 burn heal from regular ointment + - tweak: Regular bandages will now disinfect (in addition to stopping bleeding as + they previously did) + - bugfix: Fixes a few crafting recipes not having the proper category + - bugfix: Fixes laser slugs not firing lasers + - tweak: Adjusts the damage/consistency of improvised slugs + - rscadd: Adds in craftable bolas; throw them at someone to slow them down + - rscadd: Secvend starts off with e-bolas + - rscadd: Can make spears with personal crafting now + - bugfix: Fixes teacups and some other drinks having no sprite, in-hand, or object + - rscadd: adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, + and windoor assemblies + - tweak: Cablecuffs are now made by opening the cable stack's crafting menu by using + it in your hand + - bugfix: Fixes cablecuffs not having a unique in-hand icon + - bugfix: Fixes cable coils not having a unique in-hand icon + - tweak: All cablecuffs will be red, regardless of what they're produced from + - bugfix: Fixes an unlimited metal exploit + - rscadd: IV Drip sprites updated; has visual feedback for if it's injecting or + taking blood + - tweak: IV Drip injection rate dramatically increased + - rscadd: Warning ping for when someone is low on blood + - rscadd: Support for species with exotic blood type + - rscadd: Alt-Click to toggle between modes + - tweak: Sensory restoration virology symptom no longer has anti-stun properties + nor heals brain damage, but has a lower acquisition level + - tweak: Damage convert heals individual limbs instead of healing overall damage + (actual impact is low) + - rscadd: Librarian now starts off with a bookbag + - tweak: Bookbag can now hold Bibles, cult tomes, books, and spellbooks + - rscadd: Can empty a bookbag into a bookshelf + - bugfix: Fixes an exploit where you could generate wood out of thin air + - bugfix: Fixes blobspores doing more damage than intended + Fox-McCloud: + - rscadd: 'Adds in a few makeshift items/weapons: molotovs, grenade lances, golden + bikehorn, paper bags, and DIY chainsaws' + - bugfix: Fixes some personal crafting behaving as other than intended + FreeStylaLT: + - bugfix: Fixed brig cell block APCs not getting power + - bugfix: 'Fixed space buggery Kyet made :angry:' + - bugfix: Fixed missing light near labor shuttle dock + - bugfix: Fixed wrongly placed cobweb in solitary + - bugfix: Fixed basketball court not having a basketball + - rscadd: Added windows to brig processing entrance + - rscadd: Re-added the missing EOD and biohazard lockers in Armory + - rscdel: 6 gas masks from Armory + - rscadd: Added grid check into random events. + Krausus: + - tweak: The voting panel now uses the browser datum, which means it looks nicer. + - tweak: The voting panel now updates while a vote is in progress. + - tweak: When a vote is started, it will now include a link to open the vote panel, + as an alternative to typing in "vote". + - tweak: Custom votes will now show full voting results upon completion. + - bugfix: Admins should no longer lose the "cancel vote" link in the voting panel. + - bugfix: View Variables should probably stop crashing admins. + - tweak: The RnD console now shows an overlay while you're waiting for it to do + work, rather than using a separate wait screen. + - rscadd: Admins now have click shortcuts for opening a player panel, showing mob + info, and viewing variables. Specifics are in Hotkey Help. + Kyep: + - rscadd: Admins can now see attacks against SSD players more easily. + - tweak: Clarified the text you get when examining a SSD player. + - bugfix: It is now possible for admins to remove a person's vamp thrall status. + - rscadd: Adds Vox, Greytide & Soviet loadouts to admin Select Equipment verb. + - bugfix: Fixes an issue with spy loadouts, and excessive access on loadouts in + general + Spacemanspark: + - bugfix: Cardboard boxes now have their own specific name in the cardboard sheets + menu. + TheDZD: + - bugfix: Fixes tempgun not recharging. + - bugfix: Fixes tempgun beams costing one tenth of what they are supposed to. + - bugfix: Admin-only jobs check for R_EVENT now, instead of R_ADMIN, as event-related + tools should. + - bugfix: Mentors should no longer get spammed by the library checkout computer + on occasion. + - bugfix: Mentors should no longer get spammed by mirrors due to body accessories. + TullyBurnalot: + - tweak: AI Integrity Restorers now destroy any AIs inside if they get EMP'd + - tweak: AI Integrity Restorers can be deconstructed if broken via explosions. This + kills the AI inside + Twinmold: + - bugfix: Can no longer destroy pods with anything other than brute and burn weapons. + - bugfix: Can no longer pull someone out of a pod when no one is actually in the + pod. + - tweak: Can now melee attack pods with weapons when harm intent is on. + - tweak: Vox Objective 4 now calculates the kills vox raiders actually have, instead + of always complete. + Ty-Omaha: + - tweak: Gives Combat Gloves to Code Red ERT agents. + - tweak: Gives Code Gamma Engineering ERT agents Combat Gloves. + monster860, clusterfack, and DeityLink: + - rscadd: Adds space parallax + tigercat2000: + - rscdel: Removes space parallax, due to server overhead, input lag & bugs +2016-08-01: + Crazylemon64: + - rscadd: Admins are now able to print a map of the z levels. + - rscadd: Admins are now capable of scrambling the z levels' transitions. + - bugfix: Janiborg trash bags no longer fit down disposals when empty + Fethas: + - bugfix: (Maybe?)..We actually check if the race HAS BLOOD before trying to suck + them + - rscadd: Due to various complaints from tajarans having hand cramps, glove makers + have removed plasteel from the fabric. + - tweak: Plasmaman can no longer be vampires. + - tweak: Removes the mask check on both victim AND vampire, also makes the message + a bit more obscure, so it's up to your imagination of where you are biting them + and with what. + Fox McCloud: + - tweak: Medical stacks now have 6 uses + - tweak: Medical stacks now heal 25 burn/brute + - tweak: Applying a medical stack to others is instant, no matter what + - tweak: Applying any medical stack to yourself has a 2 second delay + - tweak: Applying a splint to yourself has a 10 second delay + - tweak: No more RNG fumbling of putting splints to yourself + - tweak: Confirmation for applying medical stacks is now green + - tweak: Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, + 1 roll of gauze, and medipen. + - tweak: Amount of splints in medical vendors increased from 2 to 4 + - bugfix: Fixes weird icon updates when getting healed by medical kits + - rscadd: Adds in object burning system that allows things to be lit on fire + - tweak: being on fire should heat you up a bit quicker and do a bit more damage + - tweak: Novaflowers ignite you rather than uselessly heating you up + - tweak: Adjusts a few pyrotechnic chems to better fit with other tweaks to fire + damage + IcyV: + - rscadd: Adds a unique axe for Atmos-traitors + Krausus: + - bugfix: Probably fixed some very specific items messing up View Variables for + no adequately explicable reason. + - bugfix: Fixed round-end antagonist report failing to print due to null objectives. + Kyep: + - rscadd: Added atmos grenade kit to traitor uplink. + - bugfix: 'Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes + #5232' + TheBeoni: + - rscadd: Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security + one Added picture because i do not like that red label + TheDZD: + - bugfix: Shadowling ascendance and badmins pressing the "Destroy All Lights" button + should no longer bring the server to its knees. + - bugfix: Broken lights will no longer re-break. + TullyBurnalot: + - bugfix: Using ATMs leaves fingerprints behind + Twinmold: + - bugfix: Nuke Ops airtank connected to pipenet now. + tigercat2000: + - rscadd: Readded colored cable-cuffs. + - tweak: Making stacks of metal rods now updates the icon correctly. +2016-08-03: + Fox McCloud: + - bugfix: Fixes a rare case where the singularity would escape containment when + properly set up+contained + Krausus: + - tweak: Non-respawnable ghosts will no longer qualify for mid-round rejoining (event + antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this. + - tweak: Cryodorms will no longer produce respawnable ghosts for the first 30 minutes + of the round. + - bugfix: Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above + their cryo pod, in the spooky cryodorms. + - tweak: Cryodorms will now despawn you 90% faster if you willingly enter one. + - tweak: Suiciding in the first 30 minutes of a round will no longer allow you to + ghost and be respawnable. + - tweak: Becoming a non-respawnable ghost lasts the entire round, even if you ghost + in a respawnable manner later on. + - tweak: You can no longer spam pinging posibrains, and cannot ping them at all + if you cannot volunteer for one. + - rscadd: Missing limbs will now be grayed out on your health doll. + chopchop1614: + - bugfix: Fixed the C4 labcoat exploding bug +2016-08-08: + Ar3nn: + - bugfix: Telekinesis no longer is subject to meatspace problems + Chakirski: + - rscadd: Added animal AI holograms. + - tweak: .45 Magazine sprites for the M1911 are now longer invisible. + - tweak: Hoodies no longer look like labcoats while in hand. + - tweak: Ectoplasm spawns in cult mining rooms instead of an invisible "weapon". + - tweak: Duffel bag descriptions and names no longer contain "duffle". + - tweak: Syndicate medical duffel bags can now be seen while in hand. + Crazylemon64: + - rscadd: Adds a "Save" buildmode for admins to preserve their creations for later. + This is currently in an early stage, so don't be surprised by errors! + FlattestGuitar: + - tweak: Holy Water will no longer make you stutter for ages if you're not a cultist + Fox McCloud: + - bugfix: Fixes Orion Ship message being unheard when held in-hand + - rscadd: Adds headphones into the game as a loadout item + - tweak: Removes fireproof core malf AI power + - tweak: upgrade turrets malf AI power CPU reduced from 50 to to 30 + - tweak: Overload machine cost increased from 15 to 20 + - tweak: Override machine cost increased from 15 to 30 + - tweak: can override/overload field generators again + - tweak: Machine uprisers will slowly die if they aren't attacking someone + - rscadd: Adds in Hostile lockdown malf AI power for 30 CPU + - rscadd: Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively + - tweak: AI's no longer have flood mode on air alarms by default + - rscadd: Adds in lip reading malf AI power for 30 CPU + - tweak: Allows accessories to hypothetically grant armor to their wearer + - bugfix: Greytide spear illusions actually have an attack sound now + - bugfix: fixes the wormhole event being much shorter than intended + FreeStylaLT: + - rscadd: Walls now melt when hot + - rscadd: Added actual coated rwalls - you can make them by clicking on an existing + rwall with at least 2 plasteel in hand. Has infinite temp resistance. + - tweak: Replaced all fake coated rwalls with new rwalls in both metastation (where + they should be) and boxstation + - tweak: Bandaging someone no longer stabs your eyes with bright green + - bugfix: Fixed repainted-to-wood metal flooring in courtroom - it's now actually + wood + - bugfix: Fixed windoor in witness stand facing the wrong way + KasparoVy: + - bugfix: Traitors with the Maroon objective will no longer succeed if their target + is in a locker on the shuttle. + - bugfix: Traitors with the Assassination objective will no longer fail if their + target is assassinated/borged/debrained but on a Z-level greater than the derelict. + Krausus: + - bugfix: Fire will now totally consume you, rather than timidly hiding under your + clothes. + - bugfix: Admin freeze overlays should no longer disappear from humans until they're + actually unfrozen. + LittleBigKid2000: + - rscadd: Adds cheap sunglasses. They provide no flash protection, but are available + in the loadout and clothesmate. + Pinatacolada: + - rscadd: Makes the swedish gene spit out weird swedish chars and sounds + Ty-Omaha: + - tweak: Fixes "is too cumbersome to carry in one hand" from showing up to other + players. + Yurivw: + - bugfix: 'Condimaster now actually makes bottles. Removed: Unused options in admin + secret menu are now removed.' + chopchop1614: + - bugfix: fix bluespace crystals exploit diff --git a/html/changelogs/AutoChangeLog-pr-4996.yml b/html/changelogs/AutoChangeLog-pr-4996.yml deleted file mode 100644 index c6079f72ff3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4996.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: TullyBurnalot -delete-after: True -changes: - - tweak: "AI Integrity Restorers now destroy any AIs inside if they get EMP'd" - - tweak: "AI Integrity Restorers can be deconstructed if broken via explosions. This kills the AI inside" diff --git a/html/changelogs/AutoChangeLog-pr-5100.yml b/html/changelogs/AutoChangeLog-pr-5100.yml deleted file mode 100644 index 4da76e20694..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5100.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: A Giant-Ass Mountain of Salt -delete-after: True -changes: - - rscadd: "Re-adds PDA slot." diff --git a/html/changelogs/AutoChangeLog-pr-5108.yml b/html/changelogs/AutoChangeLog-pr-5108.yml deleted file mode 100644 index 91ad159673c..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5108.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: Twinmold -delete-after: True -changes: - - bugfix: "Can no longer destroy pods with anything other than brute and burn weapons." - - bugfix: "Can no longer pull someone out of a pod when no one is actually in the pod." - - tweak: "Can now melee attack pods with weapons when harm intent is on." diff --git a/html/changelogs/AutoChangeLog-pr-5137.yml b/html/changelogs/AutoChangeLog-pr-5137.yml deleted file mode 100644 index ec2f850e681..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5137.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Kyep -delete-after: True -changes: - - rscadd: "Admins can now see attacks against SSD players more easily." - - tweak: "Clarified the text you get when examining a SSD player." diff --git a/html/changelogs/AutoChangeLog-pr-5138.yml b/html/changelogs/AutoChangeLog-pr-5138.yml deleted file mode 100644 index c6c227bb522..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5138.yml +++ /dev/null @@ -1,11 +0,0 @@ -author: FreeStylaLT -delete-after: True -changes: - - bugfix: "Fixed brig cell block APCs not getting power" - - bugfix: "Fixed space buggery Kyet made :angry:" - - bugfix: "Fixed missing light near labor shuttle dock" - - bugfix: "Fixed wrongly placed cobweb in solitary" - - bugfix: "Fixed basketball court not having a basketball" - - rscadd: "Added windows to brig processing entrance" - - rscadd: "Re-added the missing EOD and biohazard lockers in Armory" - - rscdel: "6 gas masks from Armory" diff --git a/html/changelogs/AutoChangeLog-pr-5144.yml b/html/changelogs/AutoChangeLog-pr-5144.yml deleted file mode 100644 index e0805cd23d4..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5144.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes organ repair surgery saying an organ wasn't damaged when it actually was" - - tweak: "Removes the 1 burn heal from regular ointment" - - tweak: "Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)" diff --git a/html/changelogs/AutoChangeLog-pr-5155.yml b/html/changelogs/AutoChangeLog-pr-5155.yml deleted file mode 100644 index 2d79019ec97..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5155.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Twinmold -delete-after: True -changes: - - tweak: "Vox Objective 4 now calculates the kills vox raiders actually have, instead of always complete." diff --git a/html/changelogs/AutoChangeLog-pr-5159.yml b/html/changelogs/AutoChangeLog-pr-5159.yml deleted file mode 100644 index f61ea6e1943..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5159.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes a few crafting recipes not having the proper category" - - bugfix: "Fixes laser slugs not firing lasers" - - tweak: "Adjusts the damage/consistency of improvised slugs" - - rscadd: "Adds in craftable bolas; throw them at someone to slow them down" - - rscadd: "Secvend starts off with e-bolas" - - rscadd: "Can make spears with personal crafting now" diff --git a/html/changelogs/AutoChangeLog-pr-5161.yml b/html/changelogs/AutoChangeLog-pr-5161.yml deleted file mode 100644 index a40bea35861..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5161.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes teacups and some other drinks having no sprite, in-hand, or object" diff --git a/html/changelogs/AutoChangeLog-pr-5162.yml b/html/changelogs/AutoChangeLog-pr-5162.yml deleted file mode 100644 index ea046aab6ce..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5162.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Crazylemon64 -delete-after: True -changes: - - rscadd: "Adds an explosion buildmode" diff --git a/html/changelogs/AutoChangeLog-pr-5164.yml b/html/changelogs/AutoChangeLog-pr-5164.yml deleted file mode 100644 index a8255aa162d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5164.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: TheDZD -delete-after: True -changes: - - bugfix: "Fixes tempgun not recharging." - - bugfix: "Fixes tempgun beams costing one tenth of what they are supposed to." diff --git a/html/changelogs/AutoChangeLog-pr-5165.yml b/html/changelogs/AutoChangeLog-pr-5165.yml deleted file mode 100644 index 1ed519978b6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5165.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - rscadd: "adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies" diff --git a/html/changelogs/AutoChangeLog-pr-5170.yml b/html/changelogs/AutoChangeLog-pr-5170.yml deleted file mode 100644 index bf144623d0a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5170.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Crazylemon64 -delete-after: True -changes: - - bugfix: "\"Drop Everything\" in VV no longer causes limbs to fall to the ground." diff --git a/html/changelogs/AutoChangeLog-pr-5172.yml b/html/changelogs/AutoChangeLog-pr-5172.yml deleted file mode 100644 index d147308871a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5172.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand" - - bugfix: "Fixes cablecuffs not having a unique in-hand icon" - - bugfix: "Fixes cable coils not having a unique in-hand icon" - - tweak: "All cablecuffs will be red, regardless of what they're produced from" - - bugfix: "Fixes an unlimited metal exploit" diff --git a/html/changelogs/AutoChangeLog-pr-5173.yml b/html/changelogs/AutoChangeLog-pr-5173.yml deleted file mode 100644 index 2fd77d57ab3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5173.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: Krausus -delete-after: True -changes: - - tweak: "The voting panel now uses the browser datum, which means it looks nicer." - - tweak: "The voting panel now updates while a vote is in progress." - - tweak: "When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in \"vote\"." - - tweak: "Custom votes will now show full voting results upon completion." - - bugfix: "Admins should no longer lose the \"cancel vote\" link in the voting panel." diff --git a/html/changelogs/AutoChangeLog-pr-5178.yml b/html/changelogs/AutoChangeLog-pr-5178.yml deleted file mode 100644 index 78b2f4f927e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5178.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Krausus -delete-after: True -changes: - - bugfix: "View Variables should probably stop crashing admins." diff --git a/html/changelogs/AutoChangeLog-pr-5182.yml b/html/changelogs/AutoChangeLog-pr-5182.yml deleted file mode 100644 index 35fee785997..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5182.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: FlattestGuitar -delete-after: True -changes: - - tweak: "IAAs can now select the classic secHUD in loadouts" - - rscadd: "adds bananas and suit jackets to the loadout system" - - rscadd: "adds dress shoes and fancy sandals to the loadout system" - - bugfix: "Miners can now get the mining coat from loadouts" diff --git a/html/changelogs/AutoChangeLog-pr-5184.yml b/html/changelogs/AutoChangeLog-pr-5184.yml deleted file mode 100644 index 53372963d89..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5184.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - rscadd: "IV Drip sprites updated; has visual feedback for if it's injecting or taking blood" - - tweak: "IV Drip injection rate dramatically increased" - - rscadd: "Warning ping for when someone is low on blood" - - rscadd: "Support for species with exotic blood type" - - rscadd: "Alt-Click to toggle between modes" diff --git a/html/changelogs/AutoChangeLog-pr-5190.yml b/html/changelogs/AutoChangeLog-pr-5190.yml deleted file mode 100644 index 232f6bb3f51..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5190.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Kyep -delete-after: True -changes: - - bugfix: "It is now possible for admins to remove a person's vamp thrall status." diff --git a/html/changelogs/AutoChangeLog-pr-5191.yml b/html/changelogs/AutoChangeLog-pr-5191.yml deleted file mode 100644 index ffa6d33de26..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5191.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Krausus -delete-after: True -changes: - - tweak: "The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen." diff --git a/html/changelogs/AutoChangeLog-pr-5192.yml b/html/changelogs/AutoChangeLog-pr-5192.yml deleted file mode 100644 index 9798dd041f0..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5192.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Fox-McCloud -delete-after: True -changes: - - rscadd: "Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws" - - bugfix: "Fixes some personal crafting behaving as other than intended" diff --git a/html/changelogs/AutoChangeLog-pr-5198.yml b/html/changelogs/AutoChangeLog-pr-5198.yml deleted file mode 100644 index ab88cd6b449..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5198.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Spacemanspark -delete-after: True -changes: - - bugfix: "Cardboard boxes now have their own specific name in the cardboard sheets menu." diff --git a/html/changelogs/AutoChangeLog-pr-5200.yml b/html/changelogs/AutoChangeLog-pr-5200.yml deleted file mode 100644 index dad0ed52822..00000000000 --- a/html/changelogs/AutoChangeLog-pr-5200.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: TheDZD -delete-after: True -changes: - - bugfix: "Admin-only jobs check for R_EVENT now, instead of R_ADMIN, as event-related tools should." - - bugfix: "Mentors should no longer get spammed by the library checkout computer on occasion." - - bugfix: "Mentors should no longer get spammed by mirrors due to body accessories." diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi index 062d5b404c8..cc54e5aec0f 100644 Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ diff --git a/icons/mob/custom-synthetic.dmi b/icons/mob/custom-synthetic.dmi index 9ea7b69a397..3b75d6f2201 100644 Binary files a/icons/mob/custom-synthetic.dmi and b/icons/mob/custom-synthetic.dmi differ diff --git a/icons/mob/custom-synthetic64.dmi b/icons/mob/custom-synthetic64.dmi new file mode 100644 index 00000000000..0eb17f2b304 Binary files /dev/null and b/icons/mob/custom-synthetic64.dmi differ diff --git a/icons/mob/ears.dmi b/icons/mob/ears.dmi index 2e50f21be4e..13d5981c458 100644 Binary files a/icons/mob/ears.dmi and b/icons/mob/ears.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index bdc47e32599..2e73e0e955a 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 20ff8795432..c576412d5b9 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index c3843c0c967..1957a0aa1e0 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi index 684168c6608..16ae9885800 100644 Binary files a/icons/mob/species/vox/uniform.dmi and b/icons/mob/species/vox/uniform.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 9f851fc894c..9e263f8eb5a 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index 28096d4e1a4..7b0cd8dd62d 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/closet.dmi b/icons/obj/closet.dmi index a6c5a43008f..96e701080fb 100644 Binary files a/icons/obj/closet.dmi and b/icons/obj/closet.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 0be3a5a32d7..70d6ced3311 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 8aacc4a4178..fae0ff82715 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index f81f4ab555a..863c25a7aee 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 745f976c1ca..3cdea651719 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index f144b225160..cf3419cc1a7 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -89,6 +89,11 @@ Admin: \tF7 = Player Panel \tF8 = Admin PM \tF9 = Invisimin + +Admin ghost: +\tCtrl+Click = Player Panel +\tCtrl+Shift+Click = View Variables +\tShift+Middle Click = Mob Info "} mob.hotkey_help() diff --git a/nano/templates/chem_master.tmpl b/nano/templates/chem_master.tmpl index 0fcea280c42..ea83dac9217 100644 --- a/nano/templates/chem_master.tmpl +++ b/nano/templates/chem_master.tmpl @@ -36,8 +36,8 @@

      Containers:

      {{if data.condi}} - {{:helper.link('Create pill (10u max)', 'arrow-right', {'createpill': 1})}} - {{:helper.link('Create bottle (50u max)', 'arrow-right', {'createpill': 1})}} + {{:helper.link('Create pack (10u max)', 'arrow-right', {'createpill': 1})}} + {{:helper.link('Create bottle (50u max)', 'arrow-right', {'createbottle': 1})}} {{else}}

    Name

    Status

    Location

    Control

    [Bot.hacked ? "(!) [Bot.name]" : Bot.name] ([Bot.model])