diff --git a/_maps/map_files/generic/z2.dmm b/_maps/map_files/generic/z2.dmm index b621acee5fa..0d8cbeae00e 100644 --- a/_maps/map_files/generic/z2.dmm +++ b/_maps/map_files/generic/z2.dmm @@ -372,6 +372,8 @@ "hh" = (/turf/simulated/floor/plasteel/yellowsiding{dir = 8},/area/centcom/evac) "hi" = (/turf/simulated/floor/plasteel/warning{dir = 4},/area/centcom/evac) "hj" = (/obj/structure/cult/talisman{desc = "A altar dedicated to the Wizard's Federation"},/obj/item/weapon/kitchen/knife/ritual,/obj/item/clothing/suit/wizrobe/santa,/obj/item/clothing/head/wizard/santa,/turf/simulated/floor/plasteel/cult,/area/wizard_station) +"hk" = (/obj/item/weapon/disk/data,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) +"hl" = (/obj/item/toy/figure/syndie,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) "hm" = (/turf/indestructible/riveted,/area/syndicate_mothership) "hn" = (/obj/structure/closet/wardrobe/cargotech,/turf/simulated/floor/plasteel/loadingarea,/area/centcom/supply) "ho" = (/obj/structure/closet,/turf/simulated/floor/plasteel/warning/corner{dir = 1},/area/centcom/supply) @@ -385,11 +387,15 @@ "hw" = (/obj/structure/table/reinforced,/obj/item/weapon/paper_bin,/turf/simulated/floor/plasteel/red/side{dir = 2},/area/centcom/evac) "hx" = (/obj/structure/table/reinforced,/obj/item/toy/carpplushie,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plasteel/red/side{dir = 6},/area/centcom/evac) "hy" = (/obj/structure/table/reinforced,/obj/item/weapon/pen,/turf/simulated/floor/plasteel/red/side{dir = 2},/area/centcom/evac) +"hz" = (/turf/simulated/floor/plating/snow,/obj/structure/flora/bush,/turf/simulated/floor/plating/snow/gravsnow/corner,/area/syndicate_mothership) +"hA" = (/turf/simulated/floor/plating/snow,/obj/structure/flora/grass/brown,/turf/simulated/floor/plating/snow/gravsnow/corner,/area/syndicate_mothership) +"hB" = (/obj/structure/table/wood,/obj/item/toy/nuke,/turf/simulated/floor/wood,/area/syndicate_mothership) "hC" = (/turf/simulated/floor/plating/snow,/area/syndicate_mothership) "hD" = (/obj/structure/flora/grass/brown,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) "hE" = (/obj/structure/flora/tree/pine,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) "hF" = (/obj/structure/flora/grass/both,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) "hG" = (/turf/indestructible/fakeglass{icon_state = "fakewindows2"; dir = 6},/area/centcom/supply) +"hH" = (/obj/structure/cult/tome,/turf/simulated/floor/plasteel/cult,/area/wizard_station) "hI" = (/turf/simulated/floor/plasteel,/area/centcom/supply) "hJ" = (/turf/simulated/floor/plasteel/warning{dir = 8},/area/centcom/supply) "hK" = (/turf/simulated/floor/plasteel/green/corner{dir = 1},/area/centcom/control) @@ -399,12 +405,15 @@ "hO" = (/turf/simulated/floor/plasteel/yellowsiding{dir = 1},/area/centcom/evac) "hP" = (/turf/simulated/floor/plasteel/yellowsiding/corner{dir = 1},/area/centcom/evac) "hQ" = (/obj/machinery/door/airlock/external{name = "Supply Shuttle"; req_access_txt = "106"},/turf/simulated/floor/plasteel/delivery,/area/centcom/supply) +"hR" = (/obj/item/toy/figure/syndie,/turf/simulated/floor/plating/snow/gravsnow,/area/syndicate_mothership) "hS" = (/obj/machinery/door/airlock/centcom{name = "Centcom Supply"; req_access_txt = "106"},/turf/simulated/floor/plasteel/brown{dir = 4},/area/centcom/supply) "hT" = (/turf/simulated/floor/plasteel/brown{dir = 8},/area/centcom/control) "hU" = (/obj/machinery/door/airlock/centcom{name = "Centcom Docks"; opacity = 1; req_access_txt = "101"},/turf/simulated/floor/plasteel/black,/area/centcom/control) "hV" = (/obj/machinery/door/poddoor/preopen{id = "CentComPort"; name = "security door"},/turf/simulated/floor/plasteel/loadingarea{dir = 8},/area/centcom/control) "hW" = (/turf/simulated/floor/plasteel/warning{dir = 8},/area/centcom/evac) +"hX" = (/obj/structure/statue/uranium/nuke,/turf/simulated/floor/plating/snow/gravsnow,/area/syndicate_mothership) "hY" = (/obj/structure/flora/bush,/turf/simulated/floor/plating/snow,/area/syndicate_mothership) +"hZ" = (/turf/simulated/floor/plating/snow,/turf/simulated/floor/plating/snow/gravsnow/corner{tag = "icon-gravsnow_corner (NORTHWEST)"; icon_state = "gravsnow_corner"; dir = 9},/area/syndicate_mothership) "ia" = (/obj/machinery/computer/supplycomp,/turf/simulated/floor/plasteel/warning{dir = 8},/area/centcom/supply) "ib" = (/turf/simulated/floor/plasteel/green/corner{dir = 8},/area/centcom/control) "ic" = (/turf/simulated/floor/plasteel/warning/corner{dir = 4},/area/centcom/evac) @@ -614,7 +623,6 @@ "nw" = (/turf/simulated/floor/plasteel/green/side{dir = 4},/area/tdome/arena) "nx" = (/obj/effect/landmark{name = "tdome1"},/turf/simulated/floor/plasteel,/area/tdome/tdome1) "ny" = (/obj/structure/rack,/obj/item/clothing/under/color/green,/obj/item/clothing/shoes/sneakers/brown,/obj/item/clothing/suit/armor/tdome/green,/obj/item/clothing/head/helmet/thunderdome,/obj/item/weapon/melee/baton/loaded,/obj/item/weapon/melee/energy/sword/saber/green,/turf/simulated/floor/plasteel/black,/area/tdome/arena) -"nz" = (/obj/structure/cult/tome,/turf/simulated/floor/plasteel/cult,/area/wizard_station) "nA" = (/turf/indestructible/fakeglass{color = "#008000"; dir = 1; icon_state = "fakewindows"},/area/wizard_station) "nB" = (/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor/plasteel/cult,/area/wizard_station) "nC" = (/obj/structure/closet/crate{icon_state = "crateopen"; opened = 1},/obj/item/clothing/suit/wizrobe/red,/obj/item/clothing/head/wizard/red,/obj/item/weapon/staff,/obj/item/clothing/shoes/sandal,/turf/simulated/floor/plasteel/cult,/area/wizard_station) @@ -796,7 +804,7 @@ "rw" = (/obj/effect/landmark/abductor/agent{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship) "rx" = (/obj/effect/landmark/abductor/scientist{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship) "ry" = (/obj/effect/landmark/abductor/agent{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship) - + (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaead aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacafaiagajajakahanalapaoaqaharararararahasasasasasahatatatatatahaxauauauayam @@ -953,37 +961,37 @@ acacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacfYgCfYgCfYgnfYgCfYgCfYfYfYfYflgEgDgDgDgDgDhghfhhgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacfYgQgbgRgngngngngngTgSgUgUgVflgEgDgDgDgDhwhyhxhhgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBgBgBgBgBgBgBgQhcgRgngngnhdfYgCfYfYgUheflgEgDgDgDgDhOhOhOhPgDgDhigygzacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBhohnhphnhqgBgQgmgRgngngnhrgCgQfYhthshuflhvgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChDhChChChEhFhChChChEhChChChChChChEhChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachGhJhIhIhIhIgBgCfYhKgngngnhLfYgCfYgChMgCflhNgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChDhChChChChChChChChChChChEhChChChChChEhChChChChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachQhJhIhIhIhIhShTgngngngngngngngThUgUgUgUhVhWgDgDgDgDgDhbgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChYhChChChChChDhChChFhEhChChEhChChEhFhChEhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachGiahIhIhIhIgBgCfYibgngngnhdfYgCfYfYfYfYflicgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChChChChDhChChEhFhChChEhChFhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgAhQhJhIhIhIhIgBgQgbgRgngngniggbgQfYacacacflihgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChDhChChChChChFhChEhFhChEhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacilhJhIhIhIhIgBgQhcgRgngngnighcgQfYacacacflingDgDgDgDidididiegDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChCisisisisisisishChChChChChChChEhChChYhFhChChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacithJhIhIhIhIgBgQgmiuibgnhdivgmgQfYacacacflingDgDgDgDiiikijhhgDgDhigFacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCgGacacacacacacacgGhChChChChYhCishDishDhChEhChEhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciJhJhIhIhIhIgBiLiLiNiMiOiNiMiLiLiLacacacflingDgDgDgDgDipiohhgDgDhigHacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhChCishmhmjaiZhmhmisjbjcishmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBjijhjjhIhIgBjljkjnjmjpjojrjqjsiLacacacfljujtjtjtjwjvjygshhgDgDhigIacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhCjChmhmjDjEjEjDhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBgBgBgBjIgBgBjJjpjKjmjpjojKjpjLiLacacacflflflflflflflflgWgvgxixguflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajQjPjSjRaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhYjChmjXjWjWjWjWjYkajZkckbkekdhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkgjpjKjmjpjojKjpkhiLacacacacacacacacacacacflgDgDgDgDflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknaakpkokqjRjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCgGacacacacacacacgGhChCkuhmkvjWkwkwkxjWjWjWkzkykykyhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkAjpjKjmjpjojKjpkBiLacacacacacacacacacacacflgDjMikiiflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknkEkGkFkqkHjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChCacacacacackKisisiskLhmjWkwkNkMkwjWkPkOkckQkRhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkTkSkSkUjpkVkWkWkXiLacacacacacacacacacacacflgDkiipkjflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaajRlalbkHldlcjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChCacacacacaclhlglglgiZhmjWkwljlikwjWkPlkhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBgBgBgBgBiNlliMiLjpiLiNlliMiLacacacacacacacacacacackCgDgDgDgDflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaajRjRlnlmlnjRjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCgGacacacacacacacacaclrlqlqlqlqlsjWjWjWjWjWjWkPlkhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLltltltlujplultltltiLacacacacacacacacacacacflkYjwjwkZflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaknknjRlwlvlxjRaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacaclBlAjalgiZhmlCkwkwkwjWjWkPlDhmlElFhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLiLiLiLiLiLiLiLiOiLiLiLiLiLiLiLiLacacacacacacacacflflflflflflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaalHlGlJlIlLlKlxlMknaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacgJacgGlShmlUlTlVlTlTjWjWjWlXlWlWlYhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLlZmamamamamalZlZlZmamamamamalZiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaambmdmcmfmelLlxmhmgmiknknaaaaaaaaaaaaaaaaacacacacacachmmjhCacacacacacacacacacacacacacackuhmmmmlmmmmmnjWjWjWhmmomplYhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmqlZlZlZmrlZlZlZlZlZlZlZmrlZlZlZmqacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaknaalJmsmsmtlLlxmumhmiaamwmvaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacacacacjChmhmkOmAmzmBhmmChmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLlZmamamamamalZlZlZmamamamamalZiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaalMknaaaaknmDmFmEmGmElMknknaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacacacacmKlShmhmhmhmhmhmmLmLmNmMmPmOhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLiNlllllllllllllllllllllllllliMiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaajRjRmQjRjRjRjRjRjRmRjRjRjRjRjRjRaaknaaaaaaaaaaacacacacacachmhCgGacacacacacacacacacacacacacacacgGmTmTmTmUlShmmLmLmLmLmLmLhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVmVmVmVmVmVmVmWmXmXmXmXmXmXmXmXmXmXmXmXmXmWmVmVmVmVmVmVmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaajRmYlxlxmYjRnamZlxlxlxnbncjRnendngnfknknaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChDhChChFkcmLmLmLmLmLnqhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaanAnzlxlxnznAnBnBlxlxlxlxnCnAnEnDmsmsnFaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChYhEhDhYhmnJnJnJnJnJnKhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnLnsnLnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnMnxnMnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaanOnNlxmhlxnPmumhlxhjlxlxnRnOnTnSnVnUnXnWaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChEjChmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsobnsnsnvnumXmXmXmXmXocodocmXmXmXmXmXnwnvnxnxoenxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaofnzlxmEmuogmElxlxohlxlxlxofojoinFoklHaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChEhChYjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXocorocmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaajRoslxlxosjRotlxmhmElxlxotjRovouoxowaaaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChDhCjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnLnsnLnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnMnxnMnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaajRjRoBjRjRjRjRjRlnoClnjRjRjRjRjRknknknaaaaaaaaacacacacacachmhCacacacacachCacacacacachCacacacacachChChChCjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaamDlbaaknaaknoKlKmDaaaaknaaaaaaaaknaaaaaaaaacacacacacachmhCacacacacachCgGacacacgGhCacacacacachChChChCjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVoOoOoOoOoOmVmWmXmXmXmXmXmXmXmXmXmXmXmXmXmWmVoOoOoOoOoOmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaknknaaoPlbaaoRoQmDknaaoSaaaaaaaaaaaaaaaaaaacacacacacachmhCgGacacacgGhChChChChChChCgGacacacgGhChChChCjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVoToToToToTmVoUoVoVoVoVoVoVoVoVoVoVoVoVoVoWmVoXoXoXoXoXmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaknknaaoYmhoZaaaaaaknaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChChChChChChChCjChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVmVmVmVmVpapbpbpbpbpbpcpepdpbpbpbpbpbpamVmVmVmVmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac -acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknjRjRpfjRjRknaaknknaaaaaaaaaaaaaaacacacacacachmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacpgpapapaphpapipipipipipaphpapapapgacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBhohnhphnhqgBgQgmgRgngngnhrgCgQfYhthshuflhvgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChDhChChChEhFhChChChChChEhChChChChChkhEhChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachGhJhIhIhIhIgBgCfYhKgngngnhLfYgCfYgChMgCflhNgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChDhChChChChChChChChChChChEhChChChChChChChEhChlhChChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachQhJhIhIhIhIhShTgngngngngngngngThUgUgUgUhVhWgDgDgDgDgDhbgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChYhChChChChChDhChChFhChChEhChChEhChChEhFhChEhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachGiahIhIhIhIgBgCfYibgngngnhdfYgCfYfYfYfYflicgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChChChEhChChDhChChEhFhChChEhChFhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgAhQhJhIhIhIhIgBgQgbgRgngngniggbgQfYacacacflihgDgDgDgDgDgDgDgDgDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChDhChChChChChChChFhChEhFhChEhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacilhJhIhIhIhIgBgQhcgRgngngnighcgQfYacacacflingDgDgDgDidididiegDgDhigyacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChCisisisisisisishChChChChChFhChChChEhChChYhFhChChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacithJhIhIhIhIgBgQgmiuibgnhdivgmgQfYacacacflingDgDgDgDiiikijhhgDgDhigFacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCgGacacacacacacacgGhChChChChChChzisishAishAhChEhChEhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciJhJhIhIhIhIgBiLiLiNiMiOiNiMiLiLiLacacacflingDgDgDgDgDipiohhgDgDhigHacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhChChChCishmhmjaiZhmhmisjbjcishmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBjijhjjhIhIgBjljkjnjmjpjojrjqjsiLacacacfljujtjtjtjwjvjygshhgDgDhigIacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhChChCjChmhmjDjEjEjDhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBgBgBgBjIgBgBjJjpjKjmjpjojKjpjLiLacacacflflflflflflflflgWgvgxixguflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajQjPjSjRaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCacacacacacacacacaciYhYhChCjChmjXjWjWjWjWjYkajZkckbkekdhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkgjpjKjmjpjojKjpkhiLacacacacacacacacacacacflgDgDgDgDflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknaakpkokqjRjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChCgGacacacacacacacgGhChChChCkuhmkvjWkwkwkxjWjWjWkzkykykyhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkAjpjKjmjpjojKjpkBiLacacacacacacacacacacacflgDjMikiiflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknkEkGkFkqkHjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChCacacacacackKisisisisiskLhmjWkwkNkMkwjWkPkOkckQkRhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBkfkfkfgBkTkSkSkUjpkVkWkWkXiLacacacacacacacacacacacflgDkiipkjflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaajRlalbkHldlcjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChCacacacacaclhlglglglglgiZhmjWkwljlikwjWkPlkhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacgBgBgBgBgBiNlliMiLjpiLiNlliMiLacacacacacacacacacacackCgDgDgDgDflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaajRjRlnlmlnjRjRaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCgGacacacacacacacacaclrlqlqlqlqlqlqlsjWjWjWjWjWjWkPlkhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLltltltlujplultltltiLacacacacacacacacacacacflkYjwjwkZflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaknknjRlwlvlxjRaaaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacaclBlAjalglglgiZhmlCkwkwkwjWjWkPlDhmlElFhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLiLiLiLiLiLiLiLiOiLiLiLiLiLiLiLiLacacacacacacacacflflflflflflacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaalHlGlJlIlLlKlxlMknaaaaaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacgJacgGmTmTlShmlUlTlVlThBjWjWjWlXlWlWlYhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLlZmamamamamalZlZlZmamamamamalZiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaambmdmcmfmelLlxmhmgmiknknaaaaaaaaaaaaaaaaacacacacacachmmjhCacacacacacacacacacacacacacachChCkuhmmmmlmmmmmnjWjWjWhmmomplYhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmqlZlZlZmrlZlZlZlZlZlZlZmrlZlZlZmqacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaknaalJmsmsmtlLlxmumhmiaamwmvaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacacacachChYjChmhmkOmAmzmBhmmChmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLlZmamamamamalZlZlZmamamamamalZiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaalMknaaaaknmDmFmEmGmElMknknaaaaaaaaaaaaaaaaacacacacacachmhChCacacacacacacacacacacacacacacmKhChClShmhmhmhmhmhmmLmLmNmMmPmOhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaciLiNlllllllllllllllllllllllllliMiLacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaajRjRmQjRjRjRjRjRjRmRjRjRjRjRjRjRaaknaaaaaaaaaaacacacacacachmhCgGacacacacacacacacacacacacacacacgGhChCmTmTmTmUlShmmLmLmLmLmLmLhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVmVmVmVmVmVmVmWmXmXmXmXmXmXmXmXmXmXmXmXmXmWmVmVmVmVmVmVmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaajRmYlxlxmYjRnamZlxlxlxnbncjRnendngnfknknaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChDhChChFkcmLmLmLmLmLnqhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaanAhHlxlxhHnAnBnBlxlxlxlxnCnAnEnDmsmsnFaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChYhEhDhYhmnJnJnJnJnJnKhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnLnsnLnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnMnxnMnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaanOnNlxmhlxnPmumhlxhjlxlxnRnOnTnSnVnUnXnWaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChChChEjChmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsobnsnsnvnumXmXmXmXmXocodocmXmXmXmXmXnwnvnxnxoenxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaofhHlxmEmuogmElxlxohlxlxlxofojoinFoklHaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChEhChYhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXocorocmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaajRoslxlxosjRotlxmhmElxlxotjRovouoxowaaaaaaaaaaacacacacacachmhCacacacacacacacacacacacacacacacacachChChChCishChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnLnsnLnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnMnxnMnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaajRjRoBjRjRjRjRjRlnoClnjRjRjRjRjRknknknaaaaaaaaacacacacacachmhCacacacacachCacacacacachCacacacacachChChCkLhRmKhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVnrntnsnsnsnsnsnvnumXmXmXmXmXmXmXmXmXmXmXmXmXnwnvnxnxnxnxnxntnymVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaamDlbaaknaaknoKlKmDaaaaknaaaaaaaaknaaaaaaaaacacacacacachmhCacacacacachCgGacacacgGhCacacacacachChCjChRhXhRiYhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVoOoOoOoOoOmVmWmXmXmXmXmXmXmXmXmXmXmXmXmXmWmVoOoOoOoOoOmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaknknaaoPlbaaoRoQmDknaaoSaaaaaaaaaaaaaaaaaaacacacacacachmhCgGacacacgGhChChChChChChCgGacacacgGhChChClShRhZhChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVoToToToToTmVoUoVoVoVoVoVoVoVoVoVoVoVoVoVoWmVoXoXoXoXoXmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaknknaaoYmhoZaaaaaaknaaaaaaaaaaaaaaaaacacacacacachmhChChChChChChChChChChChChChChChChChChChChChCmThChChmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacmVmVmVmVmVmVmVpapbpbpbpbpbpcpepdpbpbpbpbpbpamVmVmVmVmVmVmVacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac +acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaknjRjRpfjRjRknaaknknaaaaaaaaaaaaaaacacacacacachmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmhmacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacpgpapapaphpapipipipipipaphpapapapgacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaajRpkpjpjjRoPnDmeplpmknaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacpgpgpnpgpgpgpgpopqpppgpgpgpgpnpgpgacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaalnpjprpjlnptpsmfpukqjRaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacpgpgpgpgpgacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac acacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaapvknjRpwpjpxjRkFpymfpuaaknaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index c43e9c33b72..60268e0c7ea 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -100,7 +100,7 @@ Passive gate is similar to the regular pump except: /obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 400, 100) + ui = new(user, src, ui_key, "atmos_pump", name, 400, 115) ui.open() /obj/machinery/atmospherics/components/binary/passive_gate/get_ui_data() @@ -144,28 +144,28 @@ Passive gate is similar to the regular pump except: return - /obj/machinery/atmospherics/components/binary/passive_gate/attack_hand(mob/user) if(..() || !user) return - add_fingerprint(usr) interact(user) -/obj/machinery/atmospherics/components/binary/passive_gate/Topic(href, href_list) +/obj/machinery/atmospherics/components/binary/passive_gate/ui_act(action, params) if(..()) return - if(href_list["power"]) - on = !on - investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") - if(href_list["set_press"]) - switch(href_list["set_press"]) - if ("max") - target_pressure = MAX_OUTPUT_PRESSURE - if ("set") - target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) - investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") + switch(action) + if("power") + on = !on + investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") + if("pressure") + switch(params["set"]) + if ("max") + target_pressure = MAX_OUTPUT_PRESSURE + if ("custom") + target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) + investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") update_icon() + return 1 /obj/machinery/atmospherics/components/binary/passive_gate/power_change() ..() diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index 5062bd6dcf3..650f06b3a68 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -108,7 +108,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 400, 100) + ui = new(user, src, ui_key, "atmos_pump", name, 400, 115) ui.open() /obj/machinery/atmospherics/components/binary/pump/get_ui_data() @@ -153,26 +153,27 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/pump/attack_hand(mob/user) - if(..() | !user) + if(..() || !user) return interact(user) -/obj/machinery/atmospherics/components/binary/pump/Topic(href,href_list) +/obj/machinery/atmospherics/components/binary/pump/ui_act(action, params) if(..()) return - if(href_list["power"]) - on = !on - investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") - if(href_list["set_press"]) - switch(href_list["set_press"]) - if ("max") - target_pressure = MAX_OUTPUT_PRESSURE - if ("set") - target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) - investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") - add_fingerprint(usr) + switch(action) + if("power") + on = !on + investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") + if("pressure") + switch(params["set"]) + if ("max") + target_pressure = MAX_OUTPUT_PRESSURE + if ("custom") + target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) + investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") update_icon() + return 1 /obj/machinery/atmospherics/components/binary/pump/power_change() ..() diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm index ead30d5e6d9..7b28aa206ab 100644 --- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm @@ -105,7 +105,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 400, 100) + ui = new(user, src, ui_key, "atmos_pump", name, 400, 115) ui.open() /obj/machinery/atmospherics/components/binary/volume_pump/get_ui_data() @@ -147,29 +147,31 @@ Thus, the two variables affect pump operation are set in New(): spawn(2) broadcast_status() update_icon() + return /obj/machinery/atmospherics/components/binary/volume_pump/attack_hand(mob/user) - if(..() | !user) + if(..() || !user) return interact(user) -/obj/machinery/atmospherics/components/binary/volume_pump/Topic(href,href_list) +/obj/machinery/atmospherics/components/binary/volume_pump/ui_act(action, params) if(..()) return - if(href_list["power"]) - on = !on - investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") - if(href_list["set_transfer_rate"]) - switch(href_list["set_transfer_rate"]) - if ("max") - transfer_rate = MAX_TRANSFER_RATE - if ("set") - transfer_rate = max(0, min(MAX_TRANSFER_RATE, safe_input("Pressure control", "Enter new transfer rate (0-[MAX_TRANSFER_RATE] L/s)", transfer_rate))) - investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos") - add_fingerprint(usr) + switch(action) + if("power") + on = !on + investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") + if("transfer") + switch(params) + if ("max") + transfer_rate = MAX_TRANSFER_RATE + if ("custom") + transfer_rate = max(0, min(MAX_TRANSFER_RATE, safe_input("Pressure control", "Enter new transfer rate (0-[MAX_TRANSFER_RATE] L/s)", transfer_rate))) + investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos") update_icon() + return 1 /obj/machinery/atmospherics/components/binary/volume_pump/power_change() ..() diff --git a/code/ATMOSPHERICS/components/components_base.dm b/code/ATMOSPHERICS/components/components_base.dm index 4429f181721..47791c124d7 100644 --- a/code/ATMOSPHERICS/components/components_base.dm +++ b/code/ATMOSPHERICS/components/components_base.dm @@ -137,10 +137,6 @@ Pipenet stuff; housekeeping T.assume_air(to_release) air_update_turf(1) -/* -I think this is NanoUI? -*/ - /obj/machinery/atmospherics/components/proc/safe_input(var/title, var/text, var/default_set) var/new_value = input(usr,text,title,default_set) as num if(usr.canUseTopic(src)) diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 11b47197251..b4498f7af6b 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -11,12 +11,9 @@ name = "gas filter" - req_access = list(access_atmospherics) - can_unwrench = 1 var/on = 0 - var/temp = null var/target_pressure = ONE_ATMOSPHERE @@ -172,7 +169,7 @@ Filter types: /obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "atmos_filter.tmpl", name, 400, 120) + ui = new(user, src, ui_key, "atmos_filter", name, 450, 145) ui.open() /obj/machinery/atmospherics/components/trinary/filter/get_ui_data() @@ -183,36 +180,35 @@ Filter types: data["filter_type"] = filter_type return data -/obj/machinery/atmospherics/components/trinary/filter/Topic(href, href_list) +/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params) if(..()) return - if(href_list["filterset"]) - src.filter_type = text2num(href_list["filterset"]) - var/filtering_name = "nothing" - switch(filter_type) - if(FILTER_PLASMA) - filtering_name = "plasma" - if(FILTER_OXYGEN) - filtering_name = "oxygen" - if(FILTER_NITROGEN) - filtering_name = "nitrogen" - if(FILTER_CARBONDIOXIDE) - filtering_name = "carbon dioxide" - if(FILTER_NITROUSOXIDE) - filtering_name = "nitrous oxide" - investigate_log("was set to filter [filtering_name] by [key_name(usr)]", "atmos") - if (href_list["temp"]) - src.temp = null - if(href_list["set_press"]) - switch(href_list["set_press"]) - if ("max") - target_pressure = MAX_OUTPUT_PRESSURE - if ("set") - target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) - investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") - if(href_list["power"]) - on=!on - investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") - add_fingerprint(usr) + switch(action) + if("power") + on=!on + investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") + if("pressure") + switch(params["set"]) + if("max") + target_pressure = MAX_OUTPUT_PRESSURE + if("custom") + target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure))) + investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") + if("filter") + src.filter_type = text2num(params["mode"]) + var/filtering_name = "nothing" + switch(filter_type) + if(FILTER_PLASMA) + filtering_name = "plasma" + if(FILTER_OXYGEN) + filtering_name = "oxygen" + if(FILTER_NITROGEN) + filtering_name = "nitrogen" + if(FILTER_CARBONDIOXIDE) + filtering_name = "carbon dioxide" + if(FILTER_NITROUSOXIDE) + filtering_name = "nitrous oxide" + investigate_log("was set to filter [filtering_name] by [key_name(usr)]", "atmos") update_icon() + return 1 diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 9e39a0b40f3..bfe5ff7fc4b 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -3,9 +3,6 @@ density = 0 name = "gas mixer" - - req_access = list(access_atmospherics) - can_unwrench = 1 var/on = 0 @@ -135,7 +132,7 @@ /obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "atmos_mixer.tmpl", name, 400, 145) + ui = new(user, src, ui_key, "atmos_mixer", name, 450, 175) ui.open() /obj/machinery/atmospherics/components/trinary/mixer/get_ui_data() @@ -147,29 +144,30 @@ data["node2_concentration"] = round(node2_concentration*100) return data -/obj/machinery/atmospherics/components/trinary/mixer/Topic(href,href_list) +/obj/machinery/atmospherics/components/trinary/mixer/ui_act(action, params) if(..()) return - if(href_list["power"]) - on = !on - investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") - if(href_list["set_press"]) - switch(href_list["set_press"]) - if ("max") - target_pressure = MAX_OUTPUT_PRESSURE - if ("set") - target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure))) - investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") - if(href_list["node1_c"]) - var/value = text2num(href_list["node1_c"]) - src.node1_concentration = max(0, min(1, src.node1_concentration + value)) - src.node2_concentration = max(0, min(1, src.node2_concentration - value)) - investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos") - if(href_list["node2_c"]) - var/value = text2num(href_list["node2_c"]) - src.node2_concentration = max(0, min(1, src.node2_concentration + value)) - src.node1_concentration = max(0, min(1, src.node1_concentration - value)) - investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos") - add_fingerprint(usr) + switch(action) + if("power") + on = !on + investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos") + if("pressure") + switch(params["set"]) + if("max") + target_pressure = MAX_OUTPUT_PRESSURE + if("custom") + target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure))) + investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos") + if("node1") + var/value = text2num(params["concentration"]) + src.node1_concentration = max(0, min(1, src.node1_concentration + value)) + src.node2_concentration = max(0, min(1, src.node2_concentration - value)) + investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos") + if("node2") + var/value = text2num(params["concentration"]) + src.node2_concentration = max(0, min(1, src.node2_concentration + value)) + src.node1_concentration = max(0, min(1, src.node1_concentration - value)) + investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos") update_icon() + return 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary_devices/cryo.dm b/code/ATMOSPHERICS/components/unary_devices/cryo.dm index 88fb4e5bc03..8931b19ff33 100644 --- a/code/ATMOSPHERICS/components/unary_devices/cryo.dm +++ b/code/ATMOSPHERICS/components/unary_devices/cryo.dm @@ -113,7 +113,7 @@ /obj/machinery/atmospherics/components/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "cryo.tmpl", name, 520, 560, state = notcontained_state) + ui = new(user, src, ui_key, "cryo", name, 520, 600, state = notcontained_state) ui.open() /obj/machinery/atmospherics/components/unary/cryo_cell/get_ui_data() @@ -166,33 +166,28 @@ data["beakerContents"] = beakerContents return data -/obj/machinery/atmospherics/components/unary/cryo_cell/Topic(href, href_list) +/obj/machinery/atmospherics/components/unary/cryo_cell/ui_act(action, params) if(..()) return - if(href_list["switchOn"]) - if(!state_open) - on = 1 - - if(href_list["switchOff"]) - on = 0 - - if(href_list["autoEject"]) - autoEject = !autoEject - - if(href_list["openCell"]) - open_machine() - - if(href_list["closeCell"]) - close_machine() - - if(href_list["ejectBeaker"]) - if(beaker) - beaker.loc = get_step(loc, SOUTH) - beaker = null - - add_fingerprint(usr) + switch(action) + if("open") + open_machine() + if("close") + close_machine() + if("autoeject") + autoEject = !autoEject + if("on") + if(!state_open) + on = 1 + if("off") + on = 0 + if("ejectbeaker") + if(beaker) + beaker.loc = get_step(loc, SOUTH) + beaker = null update_icon() + return 1 /obj/machinery/atmospherics/components/unary/cryo_cell/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/reagent_containers/glass)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 70a48136e1e..b474c8aba39 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -944,7 +944,7 @@ Turf and target are seperate in case you want to teleport some distance from a t final_x = T.x + rough_x final_y = T.y + rough_y final_z = T.z - else + else final_x = AM.x + rough_x final_y = AM.y + rough_y final_z = AM.z @@ -1353,9 +1353,9 @@ B --><-- A return L /atom/proc/contains(var/atom/location) - if(!location) - return 0 - for(location, location && location != src, location=location.loc); //semicolon is for the empty statement - if(location == src) - return 1 - return 0 \ No newline at end of file + if(!location) + return 0 + for(location, location && location != src, location=location.loc); //semicolon is for the empty statement + if(location == src) + return 1 + return 0 \ No newline at end of file diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm index eb087f9d63f..daacc696c62 100644 --- a/code/controllers/subsystem/minimap.dm +++ b/code/controllers/subsystem/minimap.dm @@ -170,7 +170,7 @@ var/datum/subsystem/minimap/SSminimap text2file(hash, hash_path) /datum/subsystem/minimap/proc/getMinimapFile(zlevel) - return "data/minimaps/map_[zlevel]" + return "data/minimaps/[MAP_NAME]_[zlevel]" /datum/subsystem/minimap/proc/sendMinimaps(client/client) for (var/z = 1 to world.maxz) diff --git a/code/controllers/subsystem/nano.dm b/code/controllers/subsystem/nano.dm index 30434484c5f..08b62d927b7 100644 --- a/code/controllers/subsystem/nano.dm +++ b/code/controllers/subsystem/nano.dm @@ -1,27 +1,27 @@ -var/datum/subsystem/nano/SSnano - -/datum/subsystem/nano - name = "NanoUI" - wait = 10 - priority = 16 - display = 6 - - can_fire = 1 // This needs to fire before round start. - - var/list/open_uis = list() // A list of open NanoUIs, grouped by src_object and ui_key. - var/list/processing_uis = list() // A list of processing NanoUIs, not grouped. - - -/datum/subsystem/nano/New() - NEW_SS_GLOBAL(SSnano) - -/datum/subsystem/nano/stat_entry() - ..("O:[open_uis.len]|P:[processing_uis.len]") // Show how many interfaces we have open/are processing. - -/datum/subsystem/nano/fire() // Process UIs. - for(var/thing in processing_uis) - var/datum/nanoui/ui = thing - if(ui && ui.src_object && ui.user) - ui.process() - continue - processing_uis.Remove(ui) +var/datum/subsystem/nano/SSnano + +/datum/subsystem/nano + name = "NanoUI" + wait = 10 + priority = 16 + display = 6 + + can_fire = 1 // This needs to fire before round start. + + var/list/open_uis = list() // A list of open NanoUIs, grouped by src_object and ui_key. + var/list/processing_uis = list() // A list of processing NanoUIs, not grouped. + + +/datum/subsystem/nano/New() + NEW_SS_GLOBAL(SSnano) + +/datum/subsystem/nano/stat_entry() + ..("O:[open_uis.len]|P:[processing_uis.len]") // Show how many interfaces we have open/are processing. + +/datum/subsystem/nano/fire() // Process UIs. + for(var/thing in processing_uis) + var/datum/nanoui/ui = thing + if(ui && ui.user && ui.src_object) + ui.process() + continue + processing_uis.Remove(ui) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 620bc4cea66..92d990c2925 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -46,7 +46,6 @@ var/list/datum/objective/objectives = list() var/list/datum/objective/special_verbs = list() - var/list/cult_words = list() var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button. var/datum/faction/faction //associated faction @@ -147,12 +146,7 @@ if(src in ticker.mode.cult) ticker.mode.cult -= src ticker.mode.update_cult_icons_removed(src) - var/datum/game_mode/cult/cult = ticker.mode - if(istype(cult)) - cult.memorize_cult_objectives(src) special_role = null - remove_objectives() - remove_antag_equip() /datum/mind/proc/remove_rev() if(src in ticker.mode.revolutionaries) @@ -342,11 +336,8 @@ text = "[text]: " if (src in ticker.mode.cult) text += "loyal|employee|CULTIST" - text += "
Give tome|amulet." -/* - if (objectives.len==0) - text += "
Objectives are empty! Set to sacrifice and escape or summon." -*/ + text += "
Equip" + else if(isloyal(current)) text += "LOYAL|employee|cultist" else @@ -1008,31 +999,9 @@ ticker.mode.add_cultist(src) message_admins("[key_name_admin(usr)] has cult'ed [current].") log_admin("[key_name(usr)] has cult'ed [current].") - if("tome") - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - usr << "Spawning tome failed!" - else - H << "A tome, a message from your new master, appears in your [where]." - if(where == "backpack") - var/obj/item/weapon/storage/B = H.back - B.orient2hud(H) - B.show_to(H) - - if("amulet") + if("equip") if (!ticker.mode.equip_cultist(current)) - usr << "Spawning amulet failed!" + usr << "equip_cultist() failed! [current]'s starting equipment will be incomplete." else if (href_list["wizard"]) switch(href_list["wizard"]) @@ -1430,34 +1399,8 @@ special_role = "Cultist" current << "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memorize_cult_objectives(src) - else - var/explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - current << "Objective #1: [explanation]" - current.memory += "Objective #1: [explanation]
" - current << "The convert rune is join blood self" - current.memory += "The convert rune is join blood self
" - - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - else - H << "A tome, a message from your new master, appears in your [where]." - - if (!ticker.mode.equip_cultist(current)) - H << "Spawning an amulet from your Master failed." + current << "Your objective is to summon Nar-Sie by building and defending a suitable shell for the Geometer. Adequate supplies can be procured through human sacrifices." + ticker.mode.equip_cultist(current) /datum/mind/proc/make_Rev() if (ticker.mode.head_revolutionaries.len>0) diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 29fe4dfd7ed..f717b4534e4 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -176,7 +176,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin /obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr) //if recharge is started is important for the trigger spells before_cast(targets) invocation(user) - if(user.ckey) + if(user && user.ckey) user.attack_log += text("\[[time_stamp()]\] [user.real_name] ([user.ckey]) cast the spell [name].") spawn(0) if(charge_type == "recharge" && recharge) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 96bbfb32c56..383f05b5841 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -727,6 +727,13 @@ var/list/uplink_items = list() gamemodes = list(/datum/game_mode/nuclear,/datum/game_mode/gang) surplus = 20 +/datum/uplink_item/device_tools/medgun + name = "Medbeam Gun" + desc = "Medical Beam Gun, useful in prolonged firefights." + item = /obj/item/weapon/gun/medbeam + cost = 15 + gamemodes = list(/datum/game_mode/nuclear) + // IMPLANTS diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index f41c8e3ad2c..8e0a96b0271 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -13,9 +13,9 @@ maxbodytemp = 360 var/mob/camera/blob/overmind = null -/mob/living/simple_animal/hostile/blob/proc/adjustcolors(a_color) - if(a_color) - color = a_color +/mob/living/simple_animal/hostile/blob/update_icons() + if(overmind) + color = overmind.blob_reagent_datum.color /mob/living/simple_animal/hostile/blob/blob_act() return @@ -58,7 +58,6 @@ ..() /mob/living/simple_animal/hostile/blob/blobspore/Life() - if(!is_zombie && isturf(src.loc)) for(var/mob/living/carbon/human/H in oview(src,1)) //Only for corpse right next to/on same tile if(H.stat == DEAD) @@ -121,19 +120,8 @@ M.loc = src.loc return ..() - /mob/living/simple_animal/hostile/blob/blobspore/update_icons() ..() - - if(overmind && overmind.blob_reagent_datum) - adjustcolors(overmind.blob_reagent_datum.color) - else - adjustcolors(color) //to ensure zombie/other overlays update - - -/mob/living/simple_animal/hostile/blob/blobspore/adjustcolors(a_color) - color = a_color - if(is_zombie) overlays.Cut() overlays = human_overlays @@ -166,9 +154,6 @@ mob_size = MOB_SIZE_LARGE gold_core_spawnable = 1 -/mob/living/simple_animal/hostile/blob/blobbernaut/blob_act() - return - /mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed) ..(gibbed) flick("blobbernaut_death", src) diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index 6f9d1d34320..d9b2553e6ea 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -17,25 +17,28 @@ /obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, offspring) blob_cores += src SSobj.processing |= src - adjustcolors(color) //so it atleast appears + update_icon() //so it atleast appears if(!overmind) create_overmind(new_overmind) if(overmind) - adjustcolors(overmind.blob_reagent_datum.color) + update_icon() if(offspring) is_offspring = 1 point_rate = new_rate ..(loc, h) -/obj/effect/blob/core/adjustcolors(a_color) +/obj/effect/blob/core/update_icon() overlays.Cut() color = null var/image/I = new('icons/mob/blob.dmi', "blob") - I.color = a_color + if(overmind) + I.color = overmind.blob_reagent_datum.color overlays += I var/image/C = new('icons/mob/blob.dmi', "blob_core_overlay") overlays += C +/obj/effect/blob/core/PulseAnimation() + return /obj/effect/blob/core/Destroy() blob_cores -= src @@ -69,21 +72,18 @@ health = min(maxhealth, health+health_regen) if(overmind) overmind.update_health() - pulseLoop(0) + Pulse_Area(overmind, 12, 4, 3) for(var/b_dir in alldirs) if(!prob(5)) continue var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir) if(B) - var/obj/effect/blob/N = B.change_to(/obj/effect/blob/shield) - if(overmind) - N.color = overmind.blob_reagent_datum.color + B.change_to(/obj/effect/blob/shield, overmind) color = null ..() /obj/effect/blob/core/proc/create_overmind(client/new_overmind, override_delay) - if(overmind_get_delay > world.time && !override_delay) return diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index e750d359d27..30ba94d4a37 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -31,8 +31,9 @@ spore_delay = world.time + 100 // 10 seconds PulseAnimation(1) var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src) - BS.color = color - BS.overmind = overmind - overmind.blob_mobs.Add(BS) + if(overmind) //if we don't have an overmind, we don't need to do anything but make a spore + BS.overmind = overmind + BS.update_icons() + overmind.blob_mobs.Add(BS) return 0 diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm index 240f67f5256..3141e98930b 100644 --- a/code/game/gamemodes/blob/blobs/node.dm +++ b/code/game/gamemodes/blob/blobs/node.dm @@ -5,6 +5,7 @@ desc = "A large, pulsating yellow mass." health = 200 maxhealth = 200 + health_regen = 3 point_return = 25 atmosblock = 1 @@ -14,15 +15,19 @@ SSobj.processing |= src ..(loc, h) -/obj/effect/blob/node/adjustcolors(a_color) +/obj/effect/blob/node/update_icon() overlays.Cut() color = null var/image/I = new('icons/mob/blob.dmi', "blob") - I.color = a_color + if(overmind) + I.color = overmind.blob_reagent_datum.color src.overlays += I var/image/C = new('icons/mob/blob.dmi', "blob_node_overlay") src.overlays += C +/obj/effect/blob/node/PulseAnimation() + return + /obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) return @@ -32,6 +37,5 @@ return ..() /obj/effect/blob/node/Life() - pulseLoop(5) - health = min(initial(health), health + 1) + Pulse_Area(overmind, 10, 3, 2) color = null diff --git a/code/game/gamemodes/blob/blobs/resource.dm b/code/game/gamemodes/blob/blobs/resource.dm index 819d991a00c..03bb6164280 100644 --- a/code/game/gamemodes/blob/blobs/resource.dm +++ b/code/game/gamemodes/blob/blobs/resource.dm @@ -21,7 +21,7 @@ PulseAnimation(1) - resource_delay = world.time + 40 // 4 seconds + resource_delay = world.time + 45 // 4 and a half seconds if(overmind) overmind.add_points(1) diff --git a/code/game/gamemodes/blob/blobs/storage.dm b/code/game/gamemodes/blob/blobs/storage.dm index e64d32fd84b..968101b6b14 100644 --- a/code/game/gamemodes/blob/blobs/storage.dm +++ b/code/game/gamemodes/blob/blobs/storage.dm @@ -1,7 +1,7 @@ /obj/effect/blob/storage name = "storage blob" icon = 'icons/mob/blob.dmi' - icon_state = "blob_resource" + icon_state = "blob_factory" desc = "A huge, smooth mass supported by tendrils." health = 60 maxhealth = 60 @@ -12,13 +12,10 @@ /obj/effect/blob/storage/creation_action() if(overmind) overmind.max_blob_points += point_bonus + overmind.storage_blobs++ /obj/effect/blob/storage/Destroy() - if(overmind) + if(overmind && overmind.storage_blobs) //if the overmind doesn't have any recorded storage blobs, don't TAKE ALL THE POINTS THEY HAVE overmind.max_blob_points -= point_bonus + overmind.storage_blobs-- return ..() - -/obj/effect/blob/storage/PulseAnimation(activate = 0) - if(activate) - ..() - return diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 0d814fd6efb..2af309967a4 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -14,6 +14,7 @@ var/obj/effect/blob/core/blob_core = null // The blob overmind's core var/blob_points = 0 var/max_blob_points = 100 + var/storage_blobs = 0 var/last_attack = 0 var/datum/reagent/blob/blob_reagent_datum = new/datum/reagent/blob() var/list/blob_mobs = list() @@ -29,7 +30,7 @@ possible_reagents.Add(new type) blob_reagent_datum = pick(possible_reagents) if(blob_core) - blob_core.adjustcolors(blob_reagent_datum.color) + blob_core.update_icon() ghostimage = image(src.icon,src,src.icon_state) ghost_darkness_images |= ghostimage //so ghosts can see the blob cursor when they disable darkness @@ -90,7 +91,7 @@ return var/message_a = say_quote(message, get_spans()) - var/rendered = "Blob Telepathy, [name]([blob_reagent_datum.name]) [message_a]" + var/rendered = "Blob Telepathy, [name]([blob_reagent_datum.name]) [message_a]" for (var/mob/M in mob_list) if(isovermind(M) || isobserver(M)) diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index 41f4788a18c..796ea7ae9d7 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -60,7 +60,7 @@ /mob/camera/blob/verb/create_resource() set category = "Blob" set name = "Create Resource Blob (40)" - set desc = "Create a resource tower which will generate points for you." + set desc = "Create a resource tower which will generate resources for you." createSpecial(40, /obj/effect/blob/resource, 4) /mob/camera/blob/verb/create_node() @@ -137,7 +137,7 @@ return if(B.point_return) add_points(B.point_return) - src << "Gained [B.point_return] resources from removing the [B]." + src << "Gained [B.point_return] resources from removing \the [B]." qdel(B) /mob/camera/blob/verb/expand_blob_power() @@ -161,14 +161,13 @@ if(!can_buy(5)) return last_attack = world.time - OB.expand(T, 0, blob_reagent_datum.color) + OB.expand(T, 0, src) for(var/mob/living/L in T) if("blob" in L.faction) //no friendly fire continue var/mob_protection = L.get_permeability_protection() blob_reagent_datum.reaction_mob(L, VAPOR, 25, 1, mob_protection) blob_reagent_datum.send_message(L) - OB.color = blob_reagent_datum.color /mob/camera/blob/verb/rally_spores_power() set category = "Blob" @@ -209,13 +208,13 @@ set category = "Blob" set name = "Blob Broadcast" set desc = "Speak with your blob spores and blobbernauts as your mouthpieces. This action is free." - var/speak_text = input(usr, "What would you like to say with your minions?", "Blob Broadcast", null) as text + var/speak_text = input(src, "What would you like to say with your minions?", "Blob Broadcast", null) as text if(!speak_text) return else - usr << "You broadcast with your minions, [speak_text]" - for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs) - if(blob_minion.stat == CONSCIOUS) + src << "You broadcast with your minions, [speak_text]" + for(var/mob/living/simple_animal/hostile/blob/blob_minion in blob_mobs) + if(blob_minion.overmind == src && blob_minion.stat == CONSCIOUS) blob_minion.say(speak_text) /mob/camera/blob/verb/chemical_reroll() @@ -227,9 +226,9 @@ var/datum/reagent/blob/B = pick((subtypesof(/datum/reagent/blob) - blob_reagent_datum.type)) blob_reagent_datum = new B for(var/obj/effect/blob/BL in blobs) - BL.adjustcolors(blob_reagent_datum.color) + BL.update_icon() for(var/mob/living/simple_animal/hostile/blob/BLO) - BLO.adjustcolors(blob_reagent_datum.color) + BLO.update_icons() src << "Your reagent is now: [blob_reagent_datum.name]!" src << "The [blob_reagent_datum.name] reagent [blob_reagent_datum.description]" @@ -237,9 +236,9 @@ set category = "Blob" set name = "*Blob Help*" set desc = "Help on how to blob." + src << "As the overmind, you can control the blob!" src << "Your blob reagent is: [blob_reagent_datum.name]!" src << "The [blob_reagent_datum.name] reagent [blob_reagent_datum.description]" - src << "As the overmind, you can control the blob!" src << "You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear." src << "Normal Blobs will expand your reach and can be upgraded into special blobs that perform certain functions." src << "You can upgrade normal blobs into the following types of blob:" diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index 82c6a955d74..2b538a48fc6 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -12,12 +12,14 @@ var/health = 30 var/maxhealth = 30 var/health_regen = 2 //how much health this blob regens when pulsed - var/health_timestamp = 0 + var/health_timestamp = 0 //we got healed when? + var/pulse_timestamp = 0 //we got pulsed when? var/brute_resist = 2 //divides brute damage by this var/fire_resist = 1 //divides burn damage by this var/atmosblock = 0 //if the blob blocks atmos and heat spread var/mob/camera/blob/overmind + /obj/effect/blob/New(loc) var/area/Ablob = get_area(loc) if(Ablob.blob_allowed) //Is this area allowed for winning as blob? @@ -34,15 +36,6 @@ /obj/effect/blob/proc/creation_action() //When it's created by the overmind, do this. return -/obj/effect/blob/proc/check_health() - if(health <= 0) - qdel(src) - return - return - -/obj/effect/blob/update_icon() //Used for normal blobs, to update icon when weakened. - return - /obj/effect/blob/Destroy() if(atmosblock) atmosblock = 0 @@ -69,6 +62,20 @@ return 0 +/obj/effect/blob/proc/check_health() + if(health <= 0) + qdel(src) //we dead now + return + return + +/obj/effect/blob/update_icon() //Updates color based on overmind color if we have an overmind. + if(overmind) + color = overmind.blob_reagent_datum.color + else + color = null + return + + /obj/effect/blob/process() Life() return @@ -81,70 +88,57 @@ /obj/effect/blob/proc/Life() return +/obj/effect/blob/proc/Pulse_Area(pulsing_overmind = overmind, claim_range = 10, pulse_range = 3, expand_range = 2) + src.Be_Pulsed() + if(claim_range) + for(var/obj/effect/blob/B in ultra_range(claim_range, src, 1)) + B.update_icon() + if(!B.overmind && !istype(B, /obj/effect/blob/core) && prob(30)) + B.overmind = pulsing_overmind //reclaim unclaimed, non-core blobs. + B.update_icon() + if(pulse_range) + for(var/obj/effect/blob/B in orange(pulse_range, src)) + B.Be_Pulsed() + if(expand_range) + src.expand() + for(var/obj/effect/blob/B in orange(expand_range, src)) + if(prob(12)) + B.expand() + return + +/obj/effect/blob/proc/Be_Pulsed() + if(pulse_timestamp <= world.time) + PulseAnimation() + ConsumeTile() + RegenHealth() + run_action() + pulse_timestamp = world.time + 10 + return 1 //we did it, we were pulsed! + return 0 //oh no we failed + /obj/effect/blob/proc/ConsumeTile() for(var/atom/A in loc) A.blob_act() /obj/effect/blob/proc/PulseAnimation() - if(!istype(src, /obj/effect/blob/core) || !istype(src, /obj/effect/blob/node)) - flick("[icon_state]_glow", src) - return - -/obj/effect/blob/proc/RegenHealth() - // All blobs heal over time when pulsed, but it has a cool down - if(health_timestamp > world.time) - return 0 - health = min(maxhealth, health+health_regen) - update_icon() - health_timestamp = world.time + 10 // 1 seconds - -/obj/effect/blob/proc/pulseLoop(num) - var/a_color - if(overmind) - a_color = overmind.blob_reagent_datum.color - for(var/i = 1; i < 8; i += i) - Pulse(num, i, a_color) - -/obj/effect/blob/proc/Pulse(pulse = 0, origin_dir = 0, a_color)//Todo: Fix spaceblob expand - - set background = BACKGROUND_ENABLED - - PulseAnimation() - ConsumeTile() - RegenHealth() - - if(run_action())//If we can do something here then we dont need to pulse more - return - - if(pulse > 30) - return//Inf loop check - - //Looking for another blob to pulse - var/list/dirs = list(1,2,4,8) - dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us - for(var/i = 1 to 4) - if(!dirs.len) - break - var/dirn = pick(dirs) - dirs.Remove(dirn) - var/turf/T = get_step(src, dirn) - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - if(!B) - expand(T,1,a_color)//No blob here so try and expand - return - B.adjustcolors(a_color) - - B.Pulse((pulse+1),get_dir(src.loc,T), a_color) - return + flick("[icon_state]_glow", src) return +/obj/effect/blob/proc/RegenHealth() //when pulsed, heal! + if(health_timestamp <= world.time) + health = min(maxhealth, health+health_regen) + update_icon() + health_timestamp = world.time + 10 //1 second between heals + return 1 + return 0 /obj/effect/blob/proc/run_action() return 0 -/obj/effect/blob/proc/expand(turf/T = null, prob = 1, a_color) - if(prob && !prob(health)) return +/obj/effect/blob/proc/expand(turf/T = null, prob = 1, controller = null) + if(prob && !prob(health)) + return if(!T) var/list/dirs = list(1,2,4,8) for(var/i = 1 to 4) @@ -157,20 +151,23 @@ T = null if(!T) return 0 - var/Blob_spawnable = 1 + var/make_blob = 1 //can we make a blob? if(istype(T, /turf/space) && prob(65)) - Blob_spawnable = 0 + make_blob = 0 playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) //Let's give some feedback that we DID try to spawn in space, since players are used to it for(var/atom/A in T) - if(A.density) //Unless density is 0, don't spawn a blob - Blob_spawnable = 0 + if(A.density) + make_blob = 0 A.blob_act() //Hit everything if(T.density) //Check for walls and such dense turfs - Blob_spawnable = 0 + make_blob = 0 T.blob_act() //Hit the turf - if(Blob_spawnable) + if(make_blob) //well, can we? var/obj/effect/blob/B = new /obj/effect/blob/normal(src.loc) - B.color = a_color + if(controller) + B.overmind = controller + else + B.overmind = overmind B.density = 1 if(T.Enter(B,src)) //NOW we can attempt to move into the tile B.density = initial(B.density) @@ -240,25 +237,19 @@ if(controller) B.overmind = controller B.creation_action() - B.adjustcolors(color) + B.update_icon() qdel(src) return B -/obj/effect/blob/proc/adjustcolors(a_color) - if(a_color) - color = a_color - return - /obj/effect/blob/examine(mob/user) ..() user << "It seems to be made of [get_chem_name()]." return /obj/effect/blob/proc/get_chem_name() - for(var/mob/camera/blob/B in mob_list) - if(lowertext(B.blob_reagent_datum.color) == lowertext(src.color)) // Goddamit why we use strings for these - return B.blob_reagent_datum.name - return "unknown" + if(overmind) + return overmind.blob_reagent_datum.name + return "an unknown variant" /obj/effect/blob/normal icon_state = "blob" @@ -269,6 +260,7 @@ brute_resist = 4 /obj/effect/blob/normal/update_icon() + ..() if(health <= 10) icon_state = "blob_damaged" name = "fragile blob" diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index cd0d3b4315a..7b43cb7958e 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -2,29 +2,11 @@ /datum/game_mode var/list/datum/mind/cult = list() - var/list/cult_objectives = list() - /proc/iscultist(mob/living/M) return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) -/proc/is_sacrifice_target(datum/mind/mind) - if(ticker.mode.name == "cult") - var/datum/game_mode/cult/cult_mode = ticker.mode - if(mind == cult_mode.sacrifice_target) - return 1 - return 0 - -/proc/is_convertable_to_cult(datum/mind/mind) - if(!istype(mind)) return 0 - if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role in list("Captain", "Chaplain"))) return 0 - if(isloyal(mind.current)) - return 0 - if (ticker.mode.name == "cult") //redundent? - if(is_sacrifice_target(mind)) return 0 - return 1 - -/proc/cultist_commune(mob/living/user, clear = 0, say = 0, message) +/proc/cultist_commune(mob/living/user, say = 0, message) if(!message) return if(say) @@ -40,10 +22,7 @@ user.whisper(message) for(var/mob/M in mob_list) if(iscultist(M) || (M in dead_mob_list)) - if(clear || !ishuman(user)) - M << "[(ishuman(user) ? "Acolyte" : "Construct")] [user]: [message]" - else //Emergency comms - M << "Acolyte ???: [message]" + M << "[(ishuman(user) ? "Acolyte" : "Construct")] [user]: [message]" log_say("[user.real_name]/[user.key] : [message]") @@ -54,42 +33,31 @@ antag_flag = ROLE_CULTIST restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel") protected_jobs = list() - required_players = 20 - required_enemies = 4 - recommended_enemies = 4 + required_players = 10 + required_enemies = 2 + recommended_enemies = 2 enemy_minimum_age = 14 - - var/finished = 0 - - var/eldergod = 1 //for the summon god objective - - var/acolytes_needed = 10 //for the survive objective - var/acolytes_survived = 0 - - var/datum/mind/sacrifice_target = null//The target to be sacrificed - + var/eldergod = 0 + var/orbs_needed = 3 + var/large_shell_summoned = 0 + var/attempts_left = 3 /datum/game_mode/cult/announce() world << "The current game mode is - Cult!" - world << "Some crewmembers are attempting to start a cult!
\nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult.
\nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever Centcom-allowed faith they had.
" + world << "Some crewmembers are attempting to start a cult!
\nCultists - summon the elder god. Sacrifice crewmembers and turn them into constructs. Remember - there is no you, there is only the cult.
\nPersonnel - Do not let the cult succeed in its mission. Deal with the cultists and any constructs that they might summon.
" /datum/game_mode/cult/pre_setup() - cult_objectives += "sacrifice" - if(prob(50)) - cult_objectives += "survive" - else - cult_objectives += "eldergod" - if(config.protect_roles_from_antagonist) restricted_jobs += protected_jobs if(config.protect_assistant_from_antagonist) restricted_jobs += "Assistant" - acolytes_needed = round(num_players()/5,1) //Scales the escape requirement with the amount of people in the round; for every 5 players, one cultist added to the count, i.e. 25 players = 5 to escape - acolytes_needed = Clamp(acolytes_needed, 1, 15) //Max at 15 and minimum at 1 - before the update, people rarely got even 15 + //cult scaling goes here + recommended_enemies = 1 + round(num_players()/8) + orbs_needed = recommended_enemies for(var/cultists_number = 1 to recommended_enemies) if(!antag_candidates.len) @@ -106,22 +74,6 @@ /datum/game_mode/cult/post_setup() modePlayer += cult - if("sacrifice" in cult_objectives) - var/list/possible_targets = get_unconvertables() - - if(!possible_targets.len) - message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && !(player.mind in cult)) - possible_targets += player.mind - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - if(!sacrifice_target) - message_admins("Cult Sacrifice: ERROR - Null target chosen!") - else - message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") - for(var/datum/mind/cult_mind in cult) equip_cultist(cult_mind.current) update_cult_icons_added(cult_mind) @@ -131,20 +83,7 @@ /datum/game_mode/cult/proc/memorize_cult_objectives(datum/mind/cult_mind) - for(var/obj_count = 1,obj_count <= cult_objectives.len,obj_count++) - var/explanation - switch(cult_objectives[obj_count]) - if("survive") - explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." - if("sacrifice") - if(sacrifice_target) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the Sacrifice rune and three acolytes to do so." - else - explanation = "Free objective." - if("eldergod") - explanation = "Summon Nar-Sie via the rune 'Call Forth The Geometer'. It will only work if nine acolytes stand on and around it." - cult_mind.current << "Objective #[obj_count]: [explanation]" - cult_mind.memory += "Objective #[obj_count]: [explanation]
" + cult_mind.current << "Your objective is to summon Nar-Sie by building and defending a suitable shell for the Geometer. Adequate supplies can be procured through human sacrifices." /datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob) if(!istype(mob)) @@ -155,20 +94,27 @@ mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." mob.dna.remove_mutation(CLOWNMUT) + . += cult_give_item(/obj/item/weapon/tome, mob) + . += cult_give_item(/obj/item/weapon/paper/talisman/supply, mob) + . += cult_give_item(/obj/item/weapon/melee/cultblade/dagger, mob) + mob << "These will help you start the cult on this station. Use them well, and remember - you are not the only one." - var/obj/item/weapon/paper/talisman/supply/T = new(mob) - var/list/slots = list ( +/datum/game_mode/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob) + var/list/slots = list( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, "right pocket" = slot_r_store, "left hand" = slot_l_hand, "right hand" = slot_r_hand, ) + var/T = new item_path(mob) + var/item_name = initial(item_path.name) var/where = mob.equip_in_one_of_slots(T, slots) if(!where) - mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately." + mob << "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1)." + return 0 else - mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well, and remember - you are not the only one." + mob << "You have a [item_name] in your [where]." mob.update_icons() if(where == "backpack") var/obj/item/weapon/storage/B = mob.back @@ -176,20 +122,18 @@ B.show_to(mob) return 1 - /datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE - if (!istype(cult_mind)) + if (!istype(cult_mind) || (cult_mind in cult)) return 0 - if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) - cult_mind.current.Paralyse(5) - cult += cult_mind - cult_mind.current.faction |= "cult" - cult_mind.current.cult_add_comm() - update_cult_icons_added(cult_mind) - cult_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the cult!" - if(jobban_isbanned(cult_mind.current, ROLE_CULTIST)) - replace_jobbaned_player(cult_mind.current, ROLE_CULTIST, ROLE_CULTIST) - return 1 + cult_mind.current.Paralyse(5) + cult += cult_mind + cult_mind.current.faction |= "cult" + cult_mind.current.cult_add_comm() + update_cult_icons_added(cult_mind) + cult_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the cult!" + if(jobban_isbanned(cult_mind.current, ROLE_CULTIST)) + replace_jobbaned_player(cult_mind.current, ROLE_CULTIST, ROLE_CULTIST) + return 1 /datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT @@ -222,85 +166,13 @@ culthud.leave_hud(cult_mind.current) set_antag_hud(cult_mind.current, null) -/datum/game_mode/cult/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && !is_convertable_to_cult(player.mind)) - ucs += player.mind - return ucs - - -/datum/game_mode/cult/proc/check_cult_victory() - var/cult_fail = 0 - if(cult_objectives.Find("survive")) - cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise - if(cult_objectives.Find("eldergod")) - cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once - if(cult_objectives.Find("sacrifice")) - if(sacrifice_target && !sacrificed.Find(sacrifice_target)) //if the target has been sacrificed, ignore this step. otherwise, add 1 to cult_fail - cult_fail++ - - return cult_fail //if any objectives aren't met, failure - - -/datum/game_mode/cult/proc/check_survive() - acolytes_survived = 0 - for(var/datum/mind/cult_mind in cult) - if (cult_mind.current && cult_mind.current.stat != DEAD) - if(cult_mind.current.onCentcom() || cult_mind.current.onSyndieBase()) - acolytes_survived++ - if(acolytes_survived>=acolytes_needed) - return 0 - else - return 1 - - /datum/game_mode/cult/declare_completion() - - if(!check_cult_victory()) + if(eldergod) feedback_set_details("round_end_result","win - cult win") - feedback_set("round_end_result",acolytes_survived) world << "The cult wins! It has succeeded in serving its dark master!" else feedback_set_details("round_end_result","loss - staff stopped the cult") - feedback_set("round_end_result",acolytes_survived) world << "The staff managed to stop the cult!" - - var/text = "" - - if(cult_objectives.len) - text += "
The cultists' objectives were:" - for(var/obj_count=1, obj_count <= cult_objectives.len, obj_count++) - var/explanation - switch(cult_objectives[obj_count]) - if("survive") - if(!check_survive()) - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!" - feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]") - else - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail." - feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]") - if("sacrifice") - if(sacrifice_target) - if(sacrifice_target in sacrificed) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!" - feedback_add_details("cult_objective","cult_sacrifice|SUCCESS") - else if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail." - feedback_add_details("cult_objective","cult_sacrifice|FAIL") - else - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)." - feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED") - if("eldergod") - if(!eldergod) - explanation = "Summon Nar-Sie. Success!" - feedback_add_details("cult_objective","cult_narsie|SUCCESS") - else - explanation = "Summon Nar-Sie. Fail." - feedback_add_details("cult_objective","cult_narsie|FAIL") - text += "
Objective #[obj_count]: [explanation]" - - world << text ..() return 1 diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index af5df6a2f62..67acdd9d67a 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -4,6 +4,7 @@ icon_state = "cultblade" item_state = "cultblade" flags = CONDUCT + sharpness = IS_SHARP w_class = 4 force = 30 throwforce = 10 @@ -31,6 +32,21 @@ user << "An overwhelming sense of nausea overpowers you!" user.Dizzy(120) +/obj/item/weapon/melee/cultblade/dagger + name = "sacrificial dagger" + desc = "A strange dagger said to be used by sinister groups for \"preparing\" a corpse before sacrificing it to their dark gods." + icon = 'icons/obj/wizard.dmi' + icon_state = "render" + w_class = 2 + force = 15 + throwforce = 25 + embed_chance = 75 + +/obj/item/weapon/melee/cultblade/dagger/attack(mob/living/target, mob/living/carbon/human/user) + ..() + if(ishuman(target)) + var/mob/living/carbon/human/H = target + H.drip(50) /obj/item/clothing/head/culthood name = "ancient cultist hood" @@ -108,3 +124,52 @@ w_class = 3 allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/internals/) armor = list(melee = 70, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + +/obj/item/summoning_orb + name = "summoning orb" + desc = "A mysterious orb that glows eerily. You could swear that it just moved on its own." + icon = 'icons/obj/cult.dmi' + icon_state = "summoning_orb" + w_class = 1 + +/obj/item/summoning_orb/afterattack(atom/target, mob/user, proximity_flag) + if(!iscultist(user)) + return ..() + if(proximity_flag && isliving(target) && iscultist(target)) + var/mob/living/L = target + if(L.stat == DEAD) + user << "You shouldn't waste that." + return ..() + target << "You feel the Geometer's essence violating your insides." + target << "It feels... good." + target.reagents.add_reagent("unholywater", 15) + qdel(src) + ..() + +/obj/item/summoning_orb/attack_self(mob/user) + if(!iscultist(user)) + return ..() + if(ticker.mode.name != "cult") + return + var/datum/game_mode/cult/cult = ticker.mode + if(!cult.attempts_left) + user << "You attempt to call out to the Geometer, but there is no answer..." + return + switch(alert(user,"Are you sure you wish to summon the large construct shell? [cult.attempts_left] attempts left!","Summoning Large Shell","Yes","No")) + if("Yes") + cult.attempts_left-- + place_down_large_shell(user) + qdel(src) + +/obj/item/summoning_orb/proc/place_down_large_shell(mob/user) + if(!(ticker.mode.name == "cult")) + user << "You attempt to call out to the Geometer for Her shell, but you fail..." + return + var/datum/game_mode/cult/cult = ticker.mode + if(cult.large_shell_summoned) + user << "Another Acolyte has already summoned Her shell. You must go forth and contact them." + return + if(cult.attempts_left <= 0) + user << "The Geometer is no longer interested in you." + new /obj/structure/constructshell/large(get_turf(src)) + cult.large_shell_summoned = 1 diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 95b685beb29..b5b5cb9d0c4 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -1,3 +1,148 @@ +/obj/structure/constructshell/large + name = "large empty shell" + icon = 'icons/obj/cult_large.dmi' + icon_state = "shell_narsie_grey" + desc = "An oversized construct shell, fit for an elder god. Only a lunatic would even dream of such a crazed contraption." + pixel_x = -16 + pixel_y = -16 + density = 1 + anchored = 0 + var/maxhealth = 200 + var/health = 200 + var/image/black_overlay = null + var/orbs = 0 + var/orbs_needed = 1 + var/time_to_win = 1800 //3 minutes + var/timer_id = null + +/obj/structure/constructshell/large/New() + ..() + if(ticker.mode.name == "cult") + var/datum/game_mode/cult/cult = ticker.mode + orbs_needed = cult.orbs_needed + black_overlay = image('icons/obj/cult_large.dmi', "shell_narsie_black") + +/obj/structure/constructshell/large/Destroy() + priority_announce("The extra-dimensional flow has ceased. All personnel should return to their routine activities.","Central Command Higher Dimensions Affairs") + if(get_security_level() == "delta") + set_security_level("red") + if(ticker.mode.name == "cult") + var/datum/game_mode/cult/cult = ticker.mode + cult.large_shell_summoned = 0 + black_overlay = null + if(timer_id) + deltimer(timer_id) + ..() + +/obj/structure/constructshell/large/examine(mob/user) + ..() + user << "You see a number of round holes on the surface of the shell. They number [orbs_needed], and [orbs ? orbs : "none"] of them [orbs > 1 ? "are" : "is"] filled." + +/obj/structure/constructshell/large/update_icon() + var/new_alpha = round((orbs/orbs_needed)*255) + if(new_alpha) + overlays -= black_overlay + black_overlay.alpha = new_alpha + overlays += black_overlay + +/obj/structure/constructshell/large/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/summoning_orb) && (orbs < orbs_needed)) + if(!iscultist(user)) + return + visible_message("\The [src] glows.") + orbs++ + qdel(O) + update_icon() + if(orbs >= orbs_needed) + start_takeover() + return + + if( (O.flags&NOBLUDGEON) || !O.force ) + return + add_fingerprint(user) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + visible_message("[user] has hit \the [src] with [O].") + if(O.damtype == BURN || O.damtype == BRUTE) + damaged(O.force) + +//this stuff is mostly copy-pasted from gang dominators, with some changes +/obj/structure/constructshell/large/proc/start_takeover() + anchored = 1 + animate(black_overlay, alpha = 255, 5, -1) + set_security_level("delta") + var/area/A = get_area(src) + var/locname = initial(A.name) + priority_announce("Figments from an eldritch god have begun pouring into [locname] from an unknown dimension. Eliminate its vessel before it reaches a critical point.","Central Command Higher Dimensions Affairs") + timer_id = addtimer(src, "summon_narnar", time_to_win) + +/obj/structure/constructshell/large/proc/damaged(damage) + health -= damage + if(health <= 0) + new /obj/item/stack/sheet/plasteel(get_turf(src)) + qdel(src) + +/obj/structure/constructshell/large/bullet_act(obj/item/projectile/P) + if(P.damage) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[src] was hit by [P].") + damaged(P.damage) + +/obj/structure/constructshell/large/attack_alien(mob/living/user) + user.do_attack_animation(src) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes against [src] with its claws.",\ + "You smash against [src] with your claws.") + damaged(15) + +/obj/structure/constructshell/large/attack_animal(mob/living/user) + if(!isanimal(user)) + return + var/mob/living/simple_animal/M = user + M.do_attack_animation(src) + if(M.melee_damage_upper <= 0) + return + damaged(M.melee_damage_upper) + +/obj/structure/constructshell/large/mech_melee_attack(obj/mecha/M) + if(M.damtype == "brute") + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[M.name] has hit [src].") + damaged(M.force) + +/obj/structure/constructshell/large/attack_hulk(mob/user) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes [src].",\ + "You punch [src].") + damaged(5) + +/obj/structure/constructshell/large/ex_act() + return //nope + +/obj/structure/constructshell/large/singularity_pull() + return //nope + +/obj/structure/constructshell/large/singularity_act(current_size, obj/singularity/S) + var/atom/target = get_edge_target_turf(src, get_dir(src, S)) + S.throw_at(target, 5, 1) //aaand nope + +/obj/structure/constructshell/large/proc/summon_narnar() + if(ticker.mode.name != "cult") + visible_message("\The [src] glows brightly once, then falls dark. It looks strangely dull and lifeless...") + log_game("Summon Nar-Sie rune failed - gametype is not cult") + return + var/datum/game_mode/cult/cult_mode = ticker.mode + if(cult_mode.eldergod) + return //this should never happen, so we don't need any special fluff + world << 'sound/effects/dimensional_rend.ogg' + world << "Rip... Rrrip... RRRRRRRRRR--" + var/turf/target_turf = get_turf(src) + spawn(40) + new /obj/singularity/narsie/large(target_turf) //Causes Nar-Sie to spawn even if the rune has been removed + cult_mode.eldergod = 1 + + /obj/structure/cult density = 1 anchored = 1 @@ -8,7 +153,6 @@ desc = "A bloodstained altar dedicated to Nar-Sie" icon_state = "talismanaltar" - /obj/structure/cult/forge name = "daemon forge" desc = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie" diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 55ce399d19a..5ccc6d9e3f2 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -1,9 +1,6 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - /* This file contains the arcane tome files as well as innate cultist emergency communications. -It also contains rune words, which are soon to be removed. */ @@ -12,7 +9,7 @@ It also contains rune words, which are soon to be removed. /mob/living/proc/cult_innate_comm() set category = "Cultist" - set name = "Imperfect Communion" + set name = "Communion" if(!iscultist(usr)) //they shouldn't have this verb, but just to be sure... return @@ -24,24 +21,7 @@ It also contains rune words, which are soon to be removed. if(!input) // TO-DO: Add some kind of filter to corrupt the inputted text return - if(ishuman(usr) || ismonkey(usr)) //Damage only applies to humans and monkeys, to allow constructs to communicate - usr.visible_message("[usr] starts clawing at \his arms with \his fingernails!", "You begin slicing open your arms with your fingernails!") - apply_damage(10,BRUTE, "l_arm") - apply_damage(10,BRUTE, "r_arm") - sleep(50) - if(usr.incapacitated()) - return //Hard to drawn intrinsic symbols when you're bleeding out in your cell. - var/turf/location = loc - if(istype(location, /turf/simulated)) // tearing your arms apart is going to spill a bit of blood, in fact thats the idea - location.add_blood(usr) // TO-DO change this to a badly drawn rune - apply_damage(10,BRUTE, "l_arm") // does a metric fuck ton of damage because this meant to be an emergency method of communication. - apply_damage(10,BRUTE, "r_arm") - if(usr.incapacitated()) - return - usr.visible_message("[usr] paints strange symbols with their own blood.", "You paint a messy rune with your own blood.") - sleep(20) - - cultist_commune(usr, 0, 1, input) + cultist_commune(usr, 0, input) return @@ -52,6 +32,13 @@ It also contains rune words, which are soon to be removed. throw_speed = 2 throw_range = 5 w_class = 2 + var/list/known_runes = null + +/obj/item/weapon/tome/New() + ..() + known_runes = shuffle(subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) + var/known_amount = round((known_runes.len)/2) + known_runes.Cut(known_amount) /obj/item/weapon/tome/examine(mob/user) ..() @@ -92,47 +79,20 @@ It also contains rune words, which are soon to be removed. open_tome(user) /obj/item/weapon/tome/proc/open_tome(mob/user) - var/choice = alert(user,"You open the tome...",,"Commune","Scribe Rune","Read Tome") + var/choice = alert(user,"You open the tome...",,"Scribe Rune","Read Tome") switch(choice) if("Read Tome") read_tome(user) if("Scribe Rune") scribe_rune(user) - if("Commune") - var/input = stripped_input(usr, "Please enter a message to tell to the other acolytes.", "Voice of Blood", "") - if(!input) - return - cultist_commune(user, 1, 0, input) /obj/item/weapon/tome/proc/read_tome(mob/user) var/text = "" text += "
Archives of the Dark One



" text += "As a member of the cult, your goals are almost or entirely impossible to complete without special aid from the Geometer's plane. The primary method of doing this are runes. These \ scribings, drawn in blood, are concentrated nodes of the magic within Nar-Sie's realm and will allow the performance of many tasks to aid you and the rest of the cult in your objectives. Runes \ - have many different names, and almost all of them are known as Rites. The only rune that is not a Rite is the Ritual of Dimensional Rending, which can only be performed with nine cultists and calls \ - forth the avatar of the Geometer herself (so long as she consents). A small description of each rune can be found below.

A rune's name and effects can be \ - revealed by examining the rune.


"/*In order to write a rune, you must know the combination of words required for the rune. These words are in the tongue of the Geometer and must be written as such. \ - A rune will always have a specific combination, and the combination for runes may be revealed by perfomring actions such as conversion or sacrifice. Once a rune has been written, any cultists can \ - examine it to find out its \"grammar\", or the words required to scribe it. To scribe the rune, the words must be entered in lowercase and separated by exactly one space. For instance, to draw a \ - Rite of Enlightenment, one would enter the sentence \"certum nahlizet ego\", which means \"join blood self\". You may guess at combinations or perform actions to discover them.

A full list of \ - the Words of Power as well as their meanings in plain English are listed below, although a more complete archive may be accessed at a research desk.

\ - The Words of Power
\ - \"ire\" is Travel
\ - \"ego\" is Self
\ - \"nahlizet\" is Blood
\ - \"certum\" is Join
\ - \"veri\" is Hell
\ - \"jatkaa\" is Other
\ - \"mgar\" is Destroy
\ - \"balaq\" is Technology
\ - \"karazet\" is See
\ - \"geeri\" is Hide

\ - A few basic runes
\ - Rite of Translocation: \"ire ego\"
\ - Rite of Enlightenment: \"certum nahlizet ego\"
\ - Rite of Tribute: \"veri nahlizet certum\"
\ - Rite of Knowledge: \"karazet nahlizet ego\"
\ -


"*/ + have many different names, and almost all of them are known as Rites. Each follower of the Geometer is only able to use a subset of these, thus you must go forth and meet your fellow followers. \ + A small description of each rune can be found below.

A rune's name and effects can be revealed by examining the rune.


" text += "Teleport
The Rite of Translocation is a unique rite in that it requires a keyword before the scribing can begin. When invoked, the rune will \ search for other Rites of Translocation with the same keyword. Assuming one is found, the user will be instantaneously transported to the location of the other rune. If more than two runes are scribed \ @@ -141,13 +101,6 @@ It also contains rune words, which are soon to be removed. text += "Teleport Other
The Rite of Forced Translocation, like the Rite of Translocation, works by teleporting the person on the rune to one of the \ same keyword. However, this rune will only work on people other than the user, allowing the user to send any living creature somewhere else.

" - text += "Summon Tome
The Rite of Knowledge is a simplistic rune. When invoked, it will summon a single arcane tome to the rune's location before vanishing. \ -

" - - text += "Convert
The Rite of Enlightment is paramount to the success of the cult. It will allow you to convert normal crew members into cultists. \ - To do this, simply place the crew member upon the rune and invoke it. This rune requires two acolytes to use. If the target to be converted is loyalty-implanted or a certain assignment, they will \ - be unable to be converted. People the Geometer wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted.

" - text += "Sacrifice
The Rite of Tribute is used to offer sacrifice to the Geometer. Simply place any living creature upon the rune and invoke it (this will not \ target cultists!). If this creature has a mind, a soul shard will be created and the creature's soul transported to it. This rune is required if the cult's objectives include the sacrifice of a crew \ member.

" @@ -157,14 +110,7 @@ It also contains rune words, which are soon to be removed. within a few seconds, they will be brought back to life, healed of all ailments.

" text += "Veil Runes
The Rite of Obscurity is a rite that will cause all nearby runes to become invisible. The runes will still be considered by other rites \ - (such as the Rite of Translocation) but will be unusuable directly.

" - - text += "Reveal Runes
The Rite of True Sight is the foil of the Rite of Obscurity. It will turn all invisible runes visible once more, in addition to causing \ - all spirits nearby to become visible.

" - - text += "Disguise Runes
Many crewmen enjoy drawing runes in crayon that resemble spell circles in order to play pranks on their fellow crewmen. The Rite of \ - False Truths takes advantage of this very joke. When invoked, all nearby runes will appear dull, precisely resembling those drawn in crayon. They still cannot be cleaned by conventional means, so \ - anyone trying to clean up the rune may become suspicious as it does not respond.

" + (such as the Rite of Translocation) but will be unusuable directly. Use the same rite once more to reveal these runes once more.

" text += "Electromagnetic Disruption
Robotic lifeforms have time and time again been the downfall of fledgling cults. The Rite of Disruption may allow you to gain the upper \ hand against these pests. By using the rune, a large electromagnetic pulse will be emitted from the rune's location.

" @@ -178,14 +124,11 @@ It also contains rune words, which are soon to be removed. rune will draw a small amount of life force from the user and make the space above the rune completely dense, rendering it impassable to all but the most complex means. The rune may be invoked again to \ undo this effect and allow passage again.

" - text += "Deafen
The Rite of the Unheard Whisper is simple. When invoked, it will cause all non-cultists within a radius of seven tiles to become \ - completely deaf for a large amount of time.

" + text += "Debilitate
The Rite of the Shadowed Mind is simple. When invoked, it will cause all non-cultists that can see its rune to become deaf, blind and mute for a \ + considerable amount of time.

" - text += "Blind
Much like the Rite of the Unheard Whisper, the Rite of the Unseen Glance serves a single purpose. Any non-cultists who can see \ - the rune will instantly be blinded for a substantial amount of time.

" - - text += "Stun
Though the Rite of Blazing Light is weak when invoked normally, using it in conjuction with the Rite of Binding makes it much more useful. \ - This rune will cause any non-cultists that can see the rune to become disoriented, disabling them for a short time.

" + text += "Stun
Though the Rite of Blazing Light is weak when invoked normally, merely disorienting and disabling nearby non-cultists, non-cultists that step on the rune \ + will be stunned without expending its power. However, the disorientation caused by this rune is quite brief, and when invoked directly, it will not remain for further invocation.

" text += "Summon Cultist
The Rite of Joined Souls requires two acolytes to use. When invoked, it will allow the user to summon a single cultist to the rune from \ any location. This will deal a moderate amount of damage to all invokers.

" @@ -204,15 +147,18 @@ It also contains rune words, which are soon to be removed. text += "Blood Boil
The Rite of Boiling Blood may be considered one of the most dangerous rites composed by the cult of Nar-Sie. When invoked, it will do a \ massive amount of damage to all non-cultist viewers, but it will also emit an explosion upon invocation. Use with caution

" + text += "Immolate
The Rite of the Cleansing Flame is a weaker offensive rite, fit to be used by a lone cultist. When its rune is invoked, it will set any non-cultists \ + that can see it on fire. However, it will also burn its user.

" + + text += "Time Stop
The Rite of Dimensional Corruption is a versatile rite that can be very strong when protecting our cult from the enemies of the Geometer. \ + As it is invoked, it will rend and reshape reality around itself, stopping time for all those who don't follow the teachings of the Geometer. However, it requires more than one ritual soul as a \ + catalyst, and its power is bound to overflow and hurt its casters.

" + text += "Manifest Spirit
If you wish to bring a spirit back from the dead with a wish for vengeance and desire to serve, the Rite of Spectral \ Manifestation can do just that. When invoked, any spirits above the rune will be brought to life as a human wearing nothing that seeks only to serve you and the Geometer. However, the spirit's link \ to reality is fragile - you must remain on top of the rune, and you will slowly take damage. Upon stepping off the rune, the spirits will dissipate, dropping their items to the ground. You may manifest \ multiple spirits with one rune, but you will rapidly take damage in doing so.

" - text += "Call Forth The Geometer
There is only one way to summon the avatar of Nar-Sie, and that is the Ritual of Dimensional Rending. This ritual, in \ - comparison to other runes, is very large, requiring a 3x3 space of empty tiles to create. To invoke the rune, nine cultists must stand on the rune, so that all of them are within its circle. Then, \ - simply invoke it. A brief tearing will be heard as the barrier between dimensions is torn open, and the avatar will come forth.


" - text += "While runes are excellent for many tasks, they lack portability. The advent of talismans has, to a degree, solved this inconvenience. Simply put, a talisman is a piece of paper with a \ rune inlaid within it. The words of the rune can be whispered in order to invoke its effects, although usually to a lesser extent. To create a talisman, simply use a Rite of Binding as described above. \ Unless stated otherwise, talismans are invoked by activating them in your hand. A list of valid rites, as well as the effects of their talisman form, can be found below.


" @@ -220,17 +166,11 @@ It also contains rune words, which are soon to be removed. text += "Talisman of Teleportation
The talisman form of the Rite of Translocation will transport the invoker to a randomly chosen rune of the same keyword, then \ disappear.

" - text += "Talisman of Tome Summoning
This talisman functions nearly identically to the rune. The talisman will attempt to place the tome in your hand \ - instead of on the ground, though this is the only advantage it has over the rune. It can be used once, then disappears.

" - - text += "Talismans of Veiling, Revealing, and Disguising
These talismans all function identically to their rune counterparts, but with less range. In addition, \ - the Talisman of True Sight will not reveal spirits. They will disappear after one use.

" + text += "Talismans of Veiling
This talisman functions identically to its rune counterpart.It will disappear after one use.

" text += "Talisman of Electromagnetic Pulse
This talisman functions like the Rite of Disruption. It disappears after one use.

" - text += "Talisman of Stunning
Without this talisman, the cult would have no way of easily acquiring targets to convert. Commonly called \"stunpapers\", this \ - talisman functions differently from others. Rather than simply reading the words, the target must be attacked directly with the talisman. The talisman will then knock down the target for a long \ - duration in addition to rendering them incapable of speech. Robotic lifeforms will suffer the effects of a heavy electromagnetic pulse instead." + text += "Talisman of Immolation
This talisman functions exactly like the Rite of Cleansing Flame. It can only be used once.

" var/datum/browser/popup = new(user, "tome", "", 800, 600) popup.set_content(text) @@ -242,10 +182,10 @@ It also contains rune words, which are soon to be removed. var/rune_to_scribe var/entered_rune_name var/list/possible_runes = list() - for(var/T in subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) + for(var/T in known_runes) var/obj/effect/rune/R = T if(initial(R.cultist_name)) - possible_runes.Add(initial(R.cultist_name)) //This is to allow the menu to let cultists select runes by name rather than by object path. I don't know a better way to do this + possible_runes += initial(R.cultist_name) //This is to allow the menu to let cultists select runes by name rather than by object path. I don't know a better way to do this if(!possible_runes.len) return entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in possible_runes diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 9be02034637..6ecc6a696c3 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,6 +1,3 @@ -var/list/sacrificed = list() -var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) - /* This file contains runes. @@ -9,18 +6,7 @@ They are drawn with an arcane tome in blood, and are distinguishable to cultists Fake runes can be drawn in crayon to fool people. Runes can either be invoked by one's self or with many different cultists. Each rune has a specific incantation that the cultists will say when invoking it. -To draw a rune, use an arcane tome and enter the words required. These words are in the tongue of the Geometer and must be entered as such. -Word definitions: -"ire" is Travel -"ego" is Self -"nahlizet" is Blood -"certum" is Join -"veri" is Hell -"jatkaa" is Other -"mgar" is Destroy -"balaq" is Technology -"karazet" is See -"geeri" is Hide +To draw a rune, use an arcane tome. */ @@ -38,7 +24,6 @@ Word definitions: mouse_opacity = 2 var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked. - var/grammar //This is only framework at the moment, but may be required to draw runes in the future var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it. var/rune_in_use = 0 // Used for some runes, this is for when you want a rune to not be usable when in use. @@ -55,7 +40,6 @@ Word definitions: if(iscultist(user) || user.stat == DEAD) //If they're a cultist or a ghost, tell them the effects user << "Name: [cultist_name]" user << "Effects: [cultist_desc]" - //user << "Words: [grammar]" user << "Required Acolytes: [req_cultists]" if(req_keyword && keyword) user << "Keyword: [keyword]" @@ -77,6 +61,9 @@ Word definitions: return if(can_invoke(user)) invoke(user) + var/oldtransform = transform + animate(src, transform = matrix()*2, alpha = 0, time = 5) //fade out + animate(transform = oldtransform, alpha = 255, time = 0) else fail_invoke(user) @@ -151,7 +138,6 @@ structure_check() searches for nearby cultist structures required for the invoca cultist_name = "malformed rune" cultist_desc = "A senseless rune written in gibberish. No good can come from invoking this." invocation = "Ra'sha yoka!" - grammar = "N/A" /obj/effect/rune/malformed/New() ..() @@ -177,7 +163,6 @@ var/list/teleport_runes = list() invocation = "Sas'so c'arta forbici!" icon_state = "2" color = rgb(0, 0, 255) - grammar = "ire ego" req_keyword = 1 /obj/effect/rune/teleport/New() @@ -216,7 +201,6 @@ var/list/teleport_other_runes = list() invocation = "Sas'so c'arta forbica!" icon_state = "1" color = rgb(200, 0, 0) - grammar = "ire jatkaa" req_keyword = 1 /obj/effect/rune/teleport_other/New() @@ -264,62 +248,6 @@ var/list/teleport_other_runes = list() "Your vision blurs, and you suddenly appear somewhere else.") target.forceMove(get_turf(selected_rune)) - -//Rite of Knowledge: Creates an arcane tome at the rune's location and destroys the rune. -/obj/effect/rune/summon_tome - cultist_name = "Summon Tome" - cultist_desc = "Pulls an arcane tome from the archives of the Geometer." - invocation = "N'ath reth sh'yro eth d'raggathnor!" - icon_state = "5" - color = rgb(0, 0, 255) - grammar = "karazet nahlizet ego" - -/obj/effect/rune/summon_tome/invoke(mob/living/user) - visible_message("A frayed tome materializes on the surface of [src], which dissolves into nothing.") - new /obj/item/weapon/tome(get_turf(src)) - qdel(src) - - -//Rite of Enlightenment: Converts a normal crewmember to the cult. Faster for every cultist nearby. -/obj/effect/rune/convert - cultist_name = "Convert" - cultist_desc = "Converts a normal crewmember on top of it to the cult. Does not work on loyalty-implanted crew." - invocation = "Mah'weyh pleggh at e'ntrath!" - icon_state = "3" - color = rgb(255, 0, 0) - grammar = "certum nahlizet ego" - req_cultists = 2 - -/obj/effect/rune/convert/invoke(mob/living/user) - var/list/convertees = list() - var/turf/T = get_turf(src) - for(var/mob/living/M in T.contents) - if(!iscultist(M) && !isloyal(M)) - convertees.Add(M) - if(!convertees.len) - fail_invoke() - log_game("Convert rune failed - no eligible convertees") - return - var/mob/living/new_cultist = pick(convertees) - if(!is_convertable_to_cult(new_cultist.mind) || new_cultist.null_rod_check()) - user << "Something is shielding [new_cultist]'s mind!" - fail_invoke() - log_game("Convert rune failed - convertee could not be converted") - if(is_sacrifice_target(new_cultist.mind)) - for(var/mob/living/M in orange(1,src)) - if(iscultist(M)) - M << "\"I desire this one for myself. SACRIFICE THEM!\"" - return - new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \ - "AAAAAAAAAAAAAA-") - ticker.mode.add_cultist(new_cultist.mind) - new_cultist.mind.special_role = "Cultist" - new_cultist << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \ - and something evil takes root." - new_cultist << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\ - " - - //Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body. /obj/effect/rune/sacrifice cultist_name = "Sacrifice" @@ -327,7 +255,6 @@ var/list/teleport_other_runes = list() icon_state = "3" invocation = "Barhah hra zar'garis!" color = rgb(255, 255, 255) - grammar = "veri nahlizet certum" rune_in_use = 0 /obj/effect/rune/sacrifice/New() @@ -357,13 +284,13 @@ var/list/teleport_other_runes = list() fail_invoke() rune_in_use = 0 return - if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD) || is_sacrifice_target(offering.mind)) //Requires three people to sacrifice living targets or the round's target + if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD)) //Requires two people to sacrifice living targets var/cultists_nearby = 1 - for(var/mob/living/M in orange(1,src)) + for(var/mob/living/M in range(1,src)) if(iscultist(M) && M != user) cultists_nearby++ M.say(invocation) - if(cultists_nearby < 3) + if(cultists_nearby < 2) user << "[offering] is too greatly linked to the world! You need more acolytes!" fail_invoke() log_game("Sacrifice rune failed - not enough acolytes and target is living") @@ -376,29 +303,17 @@ var/list/teleport_other_runes = list() sac(offering) /obj/effect/rune/sacrifice/proc/sac(mob/living/T) - var/sacrifice_fulfilled if(T) - if(istype(T, /mob/living/simple_animal/pet/dog)) - for(var/mob/living/carbon/C in range(3,src)) - if(iscultist(C)) - C << "\"Even I have standards, such as they are!\"" - if(C.reagents) - C.reagents.add_reagent("hell_water", 2) - if(T.mind) - sacrificed.Add(T.mind) - if(is_sacrifice_target(T.mind)) - sacrifice_fulfilled = 1 PoolOrNew(/obj/effect/overlay/temp/cult/sac, src.loc) for(var/mob/living/M in range(3,src)) if(iscultist(M)) - if(sacrifice_fulfilled) - M << "\"Yes! This is the one I desire! You have done well.\"" + if(ishuman(T) || isrobot(T)) + M << "\"I accept this sacrifice.\"" else - if(ishuman(T) || isrobot(T)) - M << "\"I accept this sacrifice.\"" - else - M << "\"I accept this meager sacrifice.\"" + M << "\"I accept this meager sacrifice.\"" if(T.mind) + if(ishuman(T) || isrobot(T)) + new /obj/item/summoning_orb(get_turf(src)) var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src)) stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul() if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added @@ -417,65 +332,6 @@ var/list/teleport_other_runes = list() rune_in_use = 0 -//Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station. -/obj/effect/rune/narsie - cultist_name = "Call Forth The Geometer" - cultist_desc = "Tears apart dimensional barriers, calling forth the avatar of the Geometer." - invocation = null - req_cultists = 9 - icon = 'icons/effects/96x96.dmi' - icon_state = "rune_large" - pixel_x = -32 //So the big ol' 96x96 sprite shows up right - pixel_y = -32 - grammar = "veri certum ego" - var/used - -/obj/effect/rune/narsie/invoke(mob/living/user) - if(used) - return - if(ticker.mode.name == "cult") - var/datum/game_mode/cult/cult_mode = ticker.mode - if(!("eldergod" in cult_mode.cult_objectives)) - message_admins("[usr.real_name]([user.ckey]) tried to summon Nar-Sie when the objective was wrong") - for(var/mob/living/M in range(1,src)) - if(iscultist(M)) - M << "\"YOUR SOUL BURNS WITH YOUR ARROGANCE!!!\"" - if(M.reagents) - M.reagents.add_reagent("hell_water", 10) - M.Weaken(5) - fail_invoke() - log_game("Summon Nar-Sie rune failed - improper objective") - return - else - if(cult_mode.sacrifice_target && !(cult_mode.sacrifice_target in sacrificed)) - for(var/mob/living/M in orange(1,src)) - if(iscultist(M)) - M << "The sacrifice is not complete. The portal lacks the power to open!" - fail_invoke() - log_game("Summon Nar-Sie rune failed - sacrifice not complete") - return - if(!cult_mode.eldergod) - for(var/mob/living/M in range(1,src)) - if(iscultist(M)) - M << "The avatar of Nar-Sie is already on this plane!" - log_game("Summon Nar-Sie rune failed - already summoned") - return - //BEGIN THE SUMMONING - used = 1 - for(var/mob/living/M in range(1,src)) - if(iscultist(M)) - M.say("TOK-LYR RQA-NAP G'OLT-ULOFT!!") - world << 'sound/effects/dimensional_rend.ogg' - world << "Rip... Rrrip... RRRRRRRRRR--" - sleep(40) - new /obj/singularity/narsie/large(get_turf(user)) //Causes Nar-Sie to spawn even if the rune has been removed - cult_mode.eldergod = 0 - else - fail_invoke() - log_game("Summon Nar-Sie rune failed - gametype is not cult") - return - - //Rite of Resurrection: Requires two corpses. Revives one and gibs the other. /obj/effect/rune/raise_dead cultist_name = "Raise Dead" @@ -483,7 +339,6 @@ var/list/teleport_other_runes = list() invocation = null //Depends on the name of the user - see below icon_state = "1" color = rgb(255, 0, 0) - grammar = "nahlizet certum veri" /obj/effect/rune/raise_dead/invoke(mob/living/user) var/turf/T = get_turf(src) @@ -540,9 +395,9 @@ var/list/teleport_other_runes = list() mob_to_sacrifice.visible_message("[mob_to_sacrifice]'s body rises into the air, connected to [mob_to_revive] by a glowing tendril!") mob_to_revive.Beam(mob_to_sacrifice,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=20) sleep(20) - if(mob_to_sacrifice) //sighing noise - mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones[mob_to_revive ? ", the glowing tendril sinking into [mob_to_revive]'s body":""].") + if(!mob_to_sacrifice || !in_range(mob_to_sacrifice, src)) return + mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones[mob_to_revive ? ", the glowing tendril sinking into [mob_to_revive]'s body":""].") mob_to_sacrifice.dust() if(!mob_to_revive || mob_to_revive.stat != DEAD) visible_message("The glowing tendril snaps against the rune with a shocking crack.") @@ -561,63 +416,27 @@ var/list/teleport_other_runes = list() M.visible_message("[M] twitches.") -//Rite of Obscurity: Turns all runes within a 3-tile radius invisible. +//Rite of Obscurity: Turns all runes within a 3-tile radius invisible or reveals them again. /obj/effect/rune/hide_runes cultist_name = "Veil Runes" - cultist_desc = "Turns nearby runes invisible. They can be revealed by using the Reveal Runes rune." + cultist_desc = "Turns nearby runes invisible. They can be revealed by using this rune again." invocation = "Kla'atu barada nikt'o!" icon_state = "1" color = rgb(0,0,255) - grammar = "geeri karazet nahlizet" /obj/effect/rune/hide_runes/invoke(mob/living/user) visible_message("[src] darkens to black and vanishes.") for(var/obj/effect/rune/R in orange(3,src)) - R.visible_message("[R] fades away.") - R.invisibility = INVISIBILITY_OBSERVER - R.alpha = 100 //To help ghosts distinguish hidden runes - for(var/mob/dead/observer/O in orange(3,src)) - if(!O.invisibility) - O << "You suddenly feel as if you've vanished..." - O.invisibility = INVISIBILITY_OBSERVER + if(R.invisibility == INVISIBILITY_OBSERVER) + R.invisibility = 0 + R.alpha = initial(R.alpha) + else + R.visible_message("[R] fades away.") + R.invisibility = INVISIBILITY_OBSERVER + R.alpha = 100 //To help ghosts distinguish hidden runes qdel(src) -//Rite of True Sight: Turns ghosts and obscured runes visible -/obj/effect/rune/true_sight - cultist_name = "Reveal Runes" - cultist_desc = "Reveals all invisible objects nearby, from spirits to runes." - invocation = "Nikt'o barada kla'atu!" - icon_state = "4" - color = rgb(255, 255, 255) - grammar = "karazet geeri nahlizet" - -/obj/effect/rune/true_sight/invoke() - visible_message("[src] explodes in a flash of blinding light!") - for(var/mob/dead/observer/O in orange(3,src)) - O << "You suddenly feel very obvious..." - O.invisibility = 0 - for(var/obj/effect/rune/R in orange(3,src)) - R.invisibility = 0 - R.alpha = initial(R.alpha) - qdel(src) - - -//Rite of False Truths: Makes runes appear like crayon ones -/obj/effect/rune/make_runes_fake - cultist_name = "Disguise Runes" - cultist_desc = "Causes all nearby runes (including itself) to resemble those drawn in crayon." - invocation = "By'o isit!" - icon_state = "4" - color = rgb(0, 150, 0) - grammar = "geeri nahlizet jatkaa" - -/obj/effect/rune/make_runes_fake/invoke(mob/living/user) - visible_message("[src] flares brightly, then slowly dulls and appears mundane.") - for(var/obj/effect/rune/R in range(3,src)) - R.desc = "A rune drawn in crayon." - - //Rite of Disruption: Emits an EMP blast. /obj/effect/rune/emp cultist_name = "Electromagnetic Disruption" @@ -625,7 +444,6 @@ var/list/teleport_other_runes = list() invocation = "Ta'gh fara'qha fel d'amar det!" icon_state = "5" color = rgb(255, 0, 0) - grammar = "mgar karazet balaq" /obj/effect/rune/emp/invoke(mob/living/user) visible_message("[src] glows blue for a moment before vanishing.") @@ -645,7 +463,6 @@ var/list/teleport_other_runes = list() color = rgb(126, 23, 23) rune_in_use = 0 //One at a time, please! var/mob/living/affecting = null - grammar = "veri ire ego" /obj/effect/rune/astral/examine(mob/user) ..() @@ -713,7 +530,6 @@ var/list/teleport_other_runes = list() invocation = "Khari'd! Eske'te tannin!" icon_state = "1" color = rgb(255, 0, 0) - grammar = "mgar ire ego" /obj/effect/rune/wall/examine(mob/user) ..() @@ -729,73 +545,62 @@ var/list/teleport_other_runes = list() C.apply_damage(2, BRUTE, pick("l_arm", "r_arm")) -//Rite of the Unheard Whisper: Deafens all non-cultists nearby. +//Rite of the Shadowed Mind: Deafens, blinds and mutes all non-cultists nearby. /obj/effect/rune/deafen - cultist_name = "Deafen" - cultist_desc = "Causes all non-followers nearby to lose their hearing." + cultist_name = "Debilitate" + cultist_desc = "Causes all non-followers nearby to lose their hearing, sight and voice." invocation = "Sti kaliedir!" - grammar = "geeri jatkaa karazet" color = rgb(0, 255, 0) icon_state = "4" /obj/effect/rune/deafen/invoke(mob/living/user) - visible_message("[src] blurs for a moment before fading away.") - for(var/mob/living/carbon/C in range(7,src)) - if(!iscultist(C) && !C.null_rod_check()) - C << "The world around you goes quiet." - C.adjustEarDamage(0,50) - qdel(src) - - -//Rite of the Unseen Glance: Blinds all non-cultists nearby. -/obj/effect/rune/blind - cultist_name = "Blind" - cultist_desc = "Causes all non-followers nearby to lose their sight." - invocation = "Sti kaliesin!" - icon_state = "4" - color = rgb(0, 0, 255) - grammar = "mgar jatkaa karazet" - -/obj/effect/rune/blind/invoke(mob/living/user) visible_message("[src] emits a blinding red flash!") for(var/mob/living/carbon/C in viewers(src)) if(!iscultist(C) && !C.null_rod_check()) - C << "You can't see!" + C << "You feel oily shadows cover your senses." + C.adjustEarDamage(0,50) C.flash_eyes(1, 1) C.eye_blurry += 50 C.eye_blind += 20 + C.silent += 10 qdel(src) - -//Rite of Disorientation: Stuns all non-cultists nearby for a brief time +//Rite of Disorientation: Stuns and mutes all non-cultists nearby for a brief time /obj/effect/rune/stun cultist_name = "Stun" - cultist_desc = "Stuns all nearby non-followers for a brief time." + cultist_desc = "Stuns and mutes all nearby non-followers for a brief time." invocation = "Fuu ma'jin!" icon_state = "2" color = rgb(100, 0, 100) - grammar = "certum geeri balaq" /obj/effect/rune/stun/invoke(mob/living/user) visible_message("[src] explodes in a bright flash!") for(var/mob/living/M in viewers(src)) - if(!iscultist(M) && !M.null_rod_check()) - M << "You are disoriented by [src]!" - M.Weaken(3) - M.Stun(3) - M.flash_eyes(1,1) + stun_he(M) qdel(src) +/obj/effect/rune/stun/Crossed(atom/movable/AM) + ..() + if(isliving(AM)) + stun_he(AM) -//Rite of Joined Souls: Summons a single cultist. Requires 2 cultists. +/obj/effect/rune/stun/proc/stun_he(mob/living/M) + if(!iscultist(M) && !M.null_rod_check()) + M << "You are disoriented by [src]!" + M.Weaken(3) + M.Stun(3) + M.flash_eyes(1,1) + if(iscarbon(M)) + var/mob/living/carbon/C = M + C.silent += 3 + +//Rite of Joined Souls: Summons a single cultist. /obj/effect/rune/summon cultist_name = "Summon Cultist" cultist_desc = "Summons a single cultist to the rune." invocation = "N'ath reth sh'yro eth d'rekkathnor!" - req_cultists = 2 icon_state = "5" color = rgb(0, 255, 0) - grammar = "certum jatkaa ego" /obj/effect/rune/summon/invoke(mob/living/user) var/list/cultists = list() @@ -817,9 +622,7 @@ var/list/teleport_other_runes = list() cultist_to_summon.visible_message("[cultist_to_summon] suddenly disappears in a flash of red light!", \ "Overwhelming vertigo consumes you as you are hurled through the air!") visible_message("A foggy shape materializes atop [src] and solidifes into [cultist_to_summon]!") - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C)) - C.apply_damage(10, BRUTE, "head") + user.apply_damage(10, BRUTE, "head") cultist_to_summon.loc = get_turf(src) qdel(src) @@ -831,7 +634,6 @@ var/list/teleport_other_runes = list() invocation = null //no talisman made, no invocation. icon_state = "3" color = rgb(0, 0, 255) - grammar = "veri balaq certum" /obj/effect/rune/imbue/invoke(mob/living/user) var/turf/T = get_turf(src) @@ -881,7 +683,6 @@ var/list/teleport_other_runes = list() invocation = null //see below; doesn't say the invocation unless there's enough sheets. icon_state = "5" color = rgb(150, 150, 150) - grammar = "ire veri balaq" /obj/effect/rune/construct_shell/invoke(mob/living/user) var/turf/T = get_turf(src) @@ -911,7 +712,6 @@ var/list/teleport_other_runes = list() invocation = "N'ath reth sh'yro eth draggathnor!" icon_state = "4" color = rgb(255, 0, 0) - grammar = "veri mgar jatkaa" /obj/effect/rune/armor/invoke(mob/living/user) visible_message("With the sound of clanging metal, [src] crumbles to dust!") @@ -930,7 +730,6 @@ var/list/teleport_other_runes = list() invocation = null //see below; doesn't say the invocation if it has no targets. icon_state = "2" color = rgb(255, 0, 0) - grammar = "ire nahlizet ego" /obj/effect/rune/leeching/invoke(mob/living/user) var/turf/T = get_turf(src) @@ -961,8 +760,7 @@ var/list/teleport_other_runes = list() invocation = "Dedo ol'btoh!" icon_state = "4" color = rgb(255, 0, 0) - req_cultists = 3 - grammar = "mgar karazet nahlizet" + req_cultists = 2 /obj/effect/rune/blood_boil/invoke(mob/living/user) visible_message("[src] briefly bubbles before exploding!") @@ -973,7 +771,7 @@ var/list/teleport_other_runes = list() continue C << "Your blood boils in your veins!" C.take_overall_damage(51,51) - for(var/mob/living/carbon/M in orange(1,src)) + for(var/mob/living/carbon/M in range(1,src)) if(iscultist(M)) M.apply_damage(15, BRUTE, pick("l_arm", "r_arm")) M << "[src] saps your strength!" @@ -981,6 +779,27 @@ var/list/teleport_other_runes = list() qdel(src) +//Rite of the Cleansing Flame: Sets all non-cultists on fire. +/obj/effect/rune/flame + cultist_name = "Immolate" + cultist_desc = "Sets any non-believers who can see the rune on fire." + invocation = "Dedo va'batoh!" + icon_state = "2" + color = rgb(255, 0, 0) + +/obj/effect/rune/flame/invoke(mob/living/user) + visible_message("[src] burns away, scorching the floor below!") + for(var/mob/living/carbon/C in viewers(src)) + if(!iscultist(C) && !C.null_rod_check()) + C << "You feel your skin crisp as you burst into flames!" + C.fire_act() + user.apply_damage(15, BURN, pick("l_arm", "r_arm")) + user << "[src] burns your arms!" + var/turf/simulated/T = get_turf(src) + T.burn_tile() + qdel(src) + + //Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost. /obj/effect/rune/manifest cultist_name = "Manifest Spirit" @@ -988,7 +807,6 @@ var/list/teleport_other_runes = list() invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this icon_state = "6" color = rgb(255, 0, 0) - grammar = "nahlizet karazet ire" /obj/effect/rune/manifest/invoke(mob/living/user) if(!(user in get_turf(src))) @@ -1027,3 +845,40 @@ var/list/teleport_other_runes = list() for(var/obj/I in new_human) new_human.unEquip(I) new_human.dust() + +//Rite of Dimensional Corruption: Stops time around the rune for all non-cultists. +/obj/effect/rune/timestop + cultist_name = "Time Stop" + cultist_desc = "Stops time around the rune for all non-cultists." + invocation = "T'ak ot'marzah oahr'du!" + icon_state = "2" + color = rgb(0, 0, 255) + req_cultists = 2 + +/obj/effect/rune/timestop/invoke(mob/living/user) + visible_message("[src] flares up for a moment, and then disappears into itself!") + new /obj/effect/timestop/cult(get_turf(src)) + for(var/mob/living/carbon/M in range(1,src)) + if(iscultist(M)) + M.apply_damage(20, BRUTE, "chest") + M << "[src] temporarily stops your heart from beating!" + qdel(src) + +/obj/effect/timestop/cult + name = "Dimensional Corruption" + desc = "Something not from this world has corrupted the spacetime continuum in this exact spot." + icon = 'icons/effects/96x96.dmi' + icon_state = "rune_large" + pixel_x = -32 + pixel_y = -32 + duration = 50 + alpha = 0 + color = rgb(255, 0, 0) + +/obj/effect/timestop/cult/timestop() + animate(src, alpha = 255, time = 5, loop = -1) + SpinAnimation(speed = 5) + for(var/mob/living/M in player_list) + if(iscultist(M) || M.null_rod_check()) + immune |= M + ..() diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index e92cf3fd43e..ed9b106e3ce 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -26,8 +26,8 @@ Rite of Disorientation user << "Name: [cultist_name]" user << "Effect: [cultist_desc]" user << "Uses Remaining: [uses]" - return - ..() + else + user << "There are indecipherable images scrawled on the paper in what looks to be... blood?" /obj/item/weapon/paper/talisman/attack_self(mob/living/user) if(!iscultist(user)) @@ -70,12 +70,11 @@ Rite of Disorientation var/dat = "There are [uses] bloody runes on the parchment.
" dat += "Please choose the chant to be imbued into the fabric of reality.
" dat += "
" - dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon an arcane tome.
" dat += "Sas'so c'arta forbici! - Allows you to move to a Rite of Dislocation with the keyword of \"veri\".
" dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
" - dat += "Kla'atu barada nikt'o! - Allows you to conceal nearby runes.
" - dat += "Nikt'o barada kla'atu! - Allows you to reveal nearby runes.
" - dat += "Fuu ma'jin! - Allows you to stun a person by attacking them with the talisman.
" + dat += "Kla'atu barada nikt'o! - Allows you to conceal nearby runes, or reveal previously concealed runes.
" + dat += "Dedo va'batoh! - Allows you to set nearby non-believers on fire.
" + dat += "Barhah hra zar'garis! - A sacrifice rune appears under your feet, ready to be invoked in the name of Nar-sie.
" dat += "Kal'om neth! - Summons a soul stone, used to capure the spirits of dead or dying humans.
" dat += "Daa'ig osk! - Summons a construct shell for use with captured souls. It is too large to carry on your person.
" var/datum/browser/popup = new(user, "talisman", "", 400, 400) @@ -85,46 +84,37 @@ Rite of Disorientation return 1 /obj/item/weapon/paper/talisman/supply/Topic(href, href_list) - if(src) - if(usr.stat || usr.restrained() || !in_range(src, usr)) - return - if(href_list["rune"]) - switch(href_list["rune"]) - if("newtome") - var/obj/item/weapon/paper/talisman/summon_tome/T = new(usr) - usr.put_in_hands(T) - if("teleport") - var/obj/item/weapon/paper/talisman/teleport/T = new(usr) - T.keyword = "veri" - usr.put_in_hands(T) - if("emp") - var/obj/item/weapon/paper/talisman/emp/T = new(usr) - usr.put_in_hands(T) - if("conceal") - var/obj/item/weapon/paper/talisman/hide_runes/T = new(usr) - usr.put_in_hands(T) - if("reveal") - var/obj/item/weapon/paper/talisman/true_sight/T = new(usr) - usr.put_in_hands(T) - if("runestun") - var/obj/item/weapon/paper/talisman/stun/T = new(usr) - usr.put_in_hands(T) - if("soulstone") - var/obj/item/device/soulstone/T = new(usr) - usr.put_in_hands(T) - if("construct") - new /obj/structure/constructshell(get_turf(usr)) - src.uses-- - if(src.uses <= 0) - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.drop_item() - visible_message("[src] crumbles to dust.") - qdel(src) + if(!src || usr.stat || usr.restrained() || !in_range(src, usr)) return - else - return - + if(href_list["rune"]) + switch(href_list["rune"]) + if("teleport") + var/obj/item/weapon/paper/talisman/teleport/T = new(usr) + T.keyword = "veri" + usr.put_in_hands(T) + if("emp") + var/obj/item/weapon/paper/talisman/emp/T = new(usr) + usr.put_in_hands(T) + if("conceal") + var/obj/item/weapon/paper/talisman/hide_runes/T = new(usr) + usr.put_in_hands(T) + if("flame") + var/obj/item/weapon/paper/talisman/flame/T = new(usr) + usr.put_in_hands(T) + if("sacrune") + new /obj/effect/rune/sacrifice(get_turf(usr)) + if("soulstone") + var/obj/item/device/soulstone/T = new(usr) + usr.put_in_hands(T) + if("construct") + new /obj/structure/constructshell(get_turf(usr)) + src.uses-- + if(src.uses <= 0) + if(iscarbon(usr)) + var/mob/living/carbon/C = usr + C.drop_item() + visible_message("[src] crumbles to dust.") + qdel(src) //Rite of Translocation: Same as rune /obj/item/weapon/paper/talisman/teleport @@ -162,65 +152,24 @@ Rite of Disorientation user << "Keyword: [keyword]" -//Rite of Knowledge: Same as rune, but has two uses -/obj/item/weapon/paper/talisman/summon_tome - cultist_name = "Talisman of Tome Summoning" - cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of the Geometer." - invocation = "N'ath reth sh'yro eth d'raggathnor!" - health_cost = 1 - -/obj/item/weapon/paper/talisman/summon_tome/invoke(mob/living/user) - user.visible_message("[user]'s hand glows red for a moment.", \ - "You speak the words of the talisman!") - var/obj/item/weapon/tome/T = new(get_turf(user)) - if(user.put_in_hands(T)) - user.visible_message("A tome appears in [user]'s hand!", \ - "An arcane tome materializes in your free hand.") - else - user.visible_message("A tome appears at [user]'s feet!", \ - "An arcane tome materialzies at your feet.") - -//Rite of Obscurity: Same as rune, but less range +//Talisman of Obscurity: Same as rune /obj/item/weapon/paper/talisman/hide_runes cultist_name = "Talisman of Veiling" - cultist_desc = "A talisman that will make all runes within a small radius invisible." + cultist_desc = "A talisman that will make all runes within a small radius invisible, or make invisible runes visible again." invocation = "Kla'atu barada nikt'o!" health_cost = 1 /obj/item/weapon/paper/talisman/hide_runes/invoke(mob/living/user) user.visible_message("Dust flows from [user]'s hand.", \ "You speak the words of the talisman, veiling nearby runes.") - for(var/obj/effect/rune/R in orange(3,user)) - R.visible_message("[R] fades away.") - R.invisibility = INVISIBILITY_OBSERVER - - -//Rite of True Sight: Same as rune, but doesn't work on ghosts -/obj/item/weapon/paper/talisman/true_sight - cultist_name = "Talisman of Revealing" - cultist_desc = "A talisman that reveals nearby invisible runes." - invocation = "Nikt'o barada kla'atu!" - health_cost = 1 - -/obj/item/weapon/paper/talisman/true_sight/invoke(mob/living/user) - user.visible_message("A flash of light shines from [user]'s hand!", \ - "You speak the words of the talisman, revealing nearby runes.") - for(var/obj/effect/rune/R in orange(3,user)) - R.invisibility = 0 - - -//Rite of False Truths: Same as rune -/obj/item/weapon/paper/talisman/make_runes_fake - cultist_name = "Talisman of Disguising" - cultist_desc = "A talisman that will make nearby runes appear fake." - invocation = "By'o isit!" - health_cost = 3 - -/obj/item/weapon/paper/talisman/make_runes_fake/invoke(mob/living/user) - user.visible_message("Dust flows from [user]s hand.", \ - "You speak the words of the talisman, making nearby runes appear fake.") - for(var/obj/effect/rune/R in orange(3,user)) - R.desc = "A rune drawn in crayon." + for(var/obj/effect/rune/R in orange(3,src)) + if(R.invisibility == INVISIBILITY_OBSERVER) + R.invisibility = 0 + R.alpha = initial(R.alpha) + else + R.visible_message("[R] fades away.") + R.invisibility = INVISIBILITY_OBSERVER + R.alpha = 100 //To help ghosts distinguish hidden runes //Rite of Disruption: Same as rune @@ -236,42 +185,20 @@ Rite of Disorientation empulse(src, 4, 8) -//Rite of Disorientation: Stuns and mutes a single target for quite some time -/obj/item/weapon/paper/talisman/stun - cultist_name = "Talisman of Stunning" - cultist_desc = "A talisman that will stun and mute a single target. To use, attack target directly." - invocation = "Fuu ma'jin!" - health_cost = 10 //A lot of health because of how powerful this is +//Rite of the Cleansing Flame: Same as rune +/obj/item/weapon/paper/talisman/flame + cultist_name = "Talisman of Immolation" + cultist_desc = "A talisman that sets any non-believers who can see you on fire." + invocation = "Dedo va'batoh!" + health_cost = 10 -/obj/item/weapon/paper/talisman/stun/attack_self(mob/living/user) - if(iscultist(user)) - user << "To use this talisman, attack the target directly." - else - user << "There are indecipherable images scrawled on the paper in what looks to be... blood?" - -/obj/item/weapon/paper/talisman/stun/attack(mob/living/target, mob/living/user) - if(iscultist(user)) - user.whisper(invocation) - user.visible_message("[user] holds up [src], which explodes in a flash of red light!", \ - "You stun [target] with the talisman!") - var/obj/item/weapon/nullrod/N = locate() in target - if(N) - target.visible_message("[target]'s null rod absorbs the talisman's light!", \ - "Your null rod absorbs the blinding light!") - else - target.Weaken(10) - target.Stun(10) - target.flash_eyes(1,1) - if(issilicon(target)) - var/mob/living/silicon/S = target - S.emp_act(1) - if(iscarbon(target)) - var/mob/living/carbon/C = target - C.silent += 10 - user.drop_item() - qdel(src) - return - ..() +/obj/item/weapon/paper/talisman/flame/invoke(mob/living/user) + user.visible_message("\The [src] in [user]'s hand suddenly burns away in a red flash!", \ + "You speak the words of the talisman, setting your enemies on fire.") + for(var/mob/living/carbon/C in viewers(user)) + if(!iscultist(C) && !C.null_rod_check()) + C << "You feel your skin crisp as you burst into flames!" + C.fire_act() //Rite of Arming: Equips cultist armor on the user, where available diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 378a8c7cd65..f696f271a83 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -113,6 +113,10 @@ synd_mind.current.real_name = "[syndicate_name()] [leader_title]" synd_mind.current << "You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors." synd_mind.current << "If you feel you are not up to this task, give your ID to another operative." + synd_mind.current << "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it." + + var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge + synd_mind.current.equip_to_slot_or_del(challenge, slot_r_hand) var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/weapon/card/id) if(foundIDs.len) @@ -135,6 +139,7 @@ return + /datum/game_mode/proc/forge_syndicate_objectives(datum/mind/syndicate) var/datum/objective/nuclear/syndobj = new syndobj.owner = syndicate diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm new file mode 100644 index 00000000000..c6bbd6bf636 --- /dev/null +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -0,0 +1,46 @@ +#define CHALLENGE_TIME_LIMIT 3000 +#define MIN_CHALLENGE_PLAYERS 50 + +/obj/item/device/nuclear_challenge + name = "Declaration of War (Challenge Mode)" + icon_state = "gangtool-red" + item_state = "walkietalkie" + desc = "Use to send a declaration of hostilities to the target, delaying your shuttle departure for 20 minutes while they prepare for your assault. \ + Such a brazen move will attract the attention of powerful benefactors within the Syndicate, who will supply your team with a massive amount of bonus telecrystals. \ + Must be used within five minutes, or your benefactors will lose interest." + + + +/obj/item/device/nuclear_challenge/attack_self(mob/living/user) + if(player_list.len < MIN_CHALLENGE_PLAYERS) + user << "The enemy crew is too small to be worth declaring war on." + return + if(user.z != ZLEVEL_CENTCOM) + user << "You have to be at your base to use this." + return + + if(world.time > CHALLENGE_TIME_LIMIT) + user << "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand." + return + + var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]]. Are you sure you want to alert the enemy crew?", "Declare war?", "Yes", "No") + if(are_you_sure == "No") + user << "On second thought, the element of surprise isn't so bad after all." + return + + var/war_declaration = "[user.real_name] has declared his intent to utterly destroy [station_name()] with a nuclear device, and dares the crew to try and stop them." + priority_announce(war_declaration, title = "Declaration of War", sound = 'sound/machines/Alarm.ogg') + user << "You've attracted the attention of powerful forces within the syndicate. A bonus bundle of telecrystals has been granted to your team. Great things await you if you complete the mission." + + for(var/obj/machinery/computer/shuttle/syndicate/S in machines) + S.challenge = TRUE + + var/obj/item/device/radio/uplink/U = new /obj/item/device/radio/uplink(get_turf(user)) + U.hidden_uplink.uplink_owner= "[user.key]" + U.hidden_uplink.uses = 280 + U.hidden_uplink.mode_override = /datum/game_mode/nuclear //Maybe we can have a special set of items for the challenge uplink eventually + qdel(src) + + +#undef CHALLENGE_TIME_LIMIT +#undef MIN_CHALLENGE_PLAYERS diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index fe21e018bd8..43d2b2f6ae7 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -192,7 +192,7 @@ if(khrushchev.current && khrushchev.current.client && khrushchev.current.stat != DEAD) if(ROLE_REV in khrushchev.current.client.prefs.be_special) promotable_revs += khrushchev - if(promotable_revs) + if(promotable_revs.len) var/datum/mind/stalin = pick(promotable_revs) revolutionaries -= stalin head_revolutionaries += stalin diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index eee99d5d765..d6fd311404b 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -28,9 +28,12 @@ if(!istype(M, /mob/living/carbon/human))//If target is not a human. return ..() if(istype(M, /mob/living/carbon/human/dummy)) - return..() + return ..() add_logs(user, M, "captured [M.name]'s soul", src) + if(iscultist(user) && M && M.mind) + new /obj/item/summoning_orb(get_turf(M)) + transfer_soul("VICTIM", M, user) return @@ -104,7 +107,7 @@ /obj/item/device/soulstone/proc/transfer_soul(choice as text, target, mob/user). switch(choice) if("FORCE") - if(!iscarbon(target)) //TO-DO: Add sacrifice stoning for non-organics, just because you have no body doesnt mean you dont have a soul + if(!iscarbon(target)) //TODO: Add sacrifice stoning for non-organics, just because you have no body doesnt mean you dont have a soul return 0 if(contents.len) return 0 @@ -120,12 +123,6 @@ if("VICTIM") var/mob/living/carbon/human/T = target - if(ticker.mode.name == "cult" && T.mind == ticker.mode:sacrifice_target) - if(iscultist(user)) - user << "The Geometer of blood wants this mortal sacrificed with the rune." - else - user << "The soul stone doesn't work for no apparent reason." - return 0 if(imprinted != "empty") user << "Capture failed!: The soul stone has already been imprinted with [imprinted]'s mind!" else @@ -200,7 +197,7 @@ if(stoner && iswizard(stoner)) newstruct << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." else if(stoner && iscultist(stoner)) - newstruct << "You are still bound to serve the cult, follow their orders and help them complete their goals at all costs." + newstruct << "You are still bound to serve the cult, follow their orders and help them summon the Geometer at all costs." else newstruct << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." newstruct.cancel_camera() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index fe5c1be83a6..673dfc06d2c 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -80,12 +80,13 @@ // breathable air according to human/Life() var/list/TLV = list( - "oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa - "other" = new/datum/tlv(-1, -1, 0.5, 1), // Partial pressure, kpa - "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), /* kpa */ - "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K + "oxygen" = new/datum/tlv(16,19,135,140), // Partial pressure, kpa + "nitrogen" = new/datum/tlv(-1,-1,1000,1000), // Partial pressure, kpa + "carbon dioxide" = new/datum/tlv(-1,-1,5,10), // Partial pressure, kpa + "plasma" = new/datum/tlv(-1,-1,0.2,0.5), // Partial pressure, kpa + "other" = new/datum/tlv(-1,-1,0.5,1), // Partial pressure, kpa + "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), // kPa + "temperature" = new/datum/tlv(T0C,T0C+10,T0C+40,T0C+66), // K ) /* @@ -96,22 +97,24 @@ /obj/machinery/alarm/server //req_access = list(access_rd) //no, let departaments to work together TLV = list( - "oxygen" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa - "other" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa - "pressure" = new/datum/tlv(-1, -1,-1,-1), /* kpa */ - "temperature" = new/datum/tlv(-1, -1,-1,-1), // K + "oxygen" = new/datum/tlv(-1,-1,-1,-1), // Partial pressure, kpa + "nitrogen" = new/datum/tlv(-1,-1,-1,-1), // Partial pressure, kpa + "carbon dioxide" = new/datum/tlv(-1,-1,-1,-1), // Partial pressure, kpa + "plasma" = new/datum/tlv(-1,-1,-1,-1), // Partial pressure, kpa + "other" = new/datum/tlv(-1,-1,-1,-1), // Partial pressure, kpa + "pressure" = new/datum/tlv(-1,-1,-1,-1), /* kpa */ + "temperature" = new/datum/tlv(-1,-1,-1,-1), // K ) /obj/machinery/alarm/kitchen_cold_room TLV = list( - "oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa - "other" = new/datum/tlv(-1, -1, 0.5, 1), // Partial pressure, kpa - "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.50,ONE_ATMOSPHERE*1.60), /* kpa */ - "temperature" = new/datum/tlv(200, 210, 273.15, 283.15), // K + "oxygen" = new/datum/tlv(16,19,135,140), // Partial pressure, kpa + "nitrogen" = new/datum/tlv(-1,-1,1000,1000), // Partial pressure, kpa + "carbon dioxide" = new/datum/tlv(-1,-1,5,10), // Partial pressure, kpa + "plasma" = new/datum/tlv(-1,-1,0.2,0.5), // Partial pressure, kpa + "other" = new/datum/tlv(-1,-1,0.5,1), // Partial pressure, kpa + "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), // kPa + "temperature" = new/datum/tlv(200,210,273.15,283.15), // K ) //all air alarms in area are connected via magic @@ -187,7 +190,7 @@ /obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "air_alarm.tmpl", name, 480, 625) + ui = new(user, src, ui_key, "air_alarm", name, 480, 660) ui.open() /obj/machinery/alarm/get_ui_data(mob/user) @@ -253,7 +256,7 @@ if(!location) return var/datum/gas_mixture/environment = location.return_air() - var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen + var/total = environment.oxygen + environment.nitrogen + environment.carbon_dioxide + environment.toxins var/list/environment_data = list() data["atmos_alarm"] = alarm_area.atmosalm @@ -272,9 +275,13 @@ var/oxygen_danger = cur_tlv.get_danger_level(environment.oxygen*partial_pressure) environment_data += list(list("name" = "Oxygen", "value" = environment.oxygen / total * 100, "unit" = "%", "danger_level" = oxygen_danger)) + cur_tlv = TLV["nitrogen"] + var/nitrogen_danger = cur_tlv.get_danger_level(environment.nitrogen*partial_pressure) + environment_data += list(list("name" = "Nitrogen", "value" = environment.nitrogen / total * 100, "unit" = "%", "danger_level" = nitrogen_danger)) + cur_tlv = TLV["carbon dioxide"] var/carbon_dioxide_danger = cur_tlv.get_danger_level(environment.carbon_dioxide*partial_pressure) - environment_data += list(list("name" = "Carbon dioxide", "value" = environment.carbon_dioxide / total * 100, "unit" = "%", "danger_level" = carbon_dioxide_danger)) + environment_data += list(list("name" = "Carbon Dioxide", "value" = environment.carbon_dioxide / total * 100, "unit" = "%", "danger_level" = carbon_dioxide_danger)) cur_tlv = TLV["plasma"] var/plasma_danger = cur_tlv.get_danger_level(environment.toxins*partial_pressure) @@ -290,6 +297,7 @@ cur_tlv = TLV["temperature"] var/temperature_danger = cur_tlv.get_danger_level(environment.temperature) environment_data += list(list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_danger)) + data["environment_data"] = environment_data /obj/machinery/alarm/proc/populate_controls(list/data) @@ -311,7 +319,8 @@ "excheck" = info["checks"]&1, "incheck" = info["checks"]&2, "direction" = info["direction"], - "external" = info["external"] + "external" = info["external"], + "extdefault"= (info["external"] == ONE_ATMOSPHERE) )) if(AALARM_SCREEN_SCRUB) data["scrubbers"] = list() @@ -348,10 +357,11 @@ var/list/thresholds = list() var/list/gas_names = list( - "oxygen" = "O2", - "carbon dioxide" = "CO2", - "plasma" = "Toxin", - "other" = "Other") + "oxygen" = "O2", + "nitrogen" = "N2", + "carbon dioxide" = "CO2", + "plasma" = "Toxin", + "other" = "Other") for (var/g in gas_names) thresholds += list(list("name" = gas_names[g], "settings" = list())) selected = TLV[g] @@ -377,7 +387,7 @@ data["thresholds"] = thresholds -/obj/machinery/alarm/Topic(href, href_list) +/obj/machinery/alarm/ui_act(action, params) if(..()) return @@ -390,78 +400,65 @@ if (usr.has_unlimited_silicon_privilege && src.aidisabled) return - if(href_list["toggleaccess"]) - if(usr.has_unlimited_silicon_privilege && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) - locked = !locked - - if(href_list["command"]) - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - if("set_external_pressure") - var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null - if(isnum(input_pressure)) - send_signal(device_id, list(href_list["command"] = input_pressure)) - return 1 - - if("reset_external_pressure") - send_signal(device_id, list("set_external_pressure" = ONE_ATMOSPHERE)) - return 1 - if( - "power", - "adjust_external_pressure", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "widenet", - "scrubbing" - ) - send_signal(device_id, list (href_list["command"] = text2num(href_list["val"]))) - spawn(3) - src.updateUsrDialog() - - if ("excheck") - send_signal(device_id, list ("checks" = text2num(href_list["val"])^1)) - - if ("incheck") - send_signal(device_id, list ("checks" = text2num(href_list["val"])^2)) - - //if("adjust_threshold") //was a good idea but required very wide window - if("set_threshold") - var/env = href_list["env"] - var/varname = href_list["var"] - var/datum/tlv/tlv = TLV[env] - var/newval = input("Enter [varname] for [env]", "Alarm triggers", tlv.vars[varname]) as num|null - - if (isnull(newval) || ..() || (locked && !(usr.has_unlimited_silicon_privilege))) - return - if (newval<0) - tlv.vars[varname] = -1 - else if (env=="temperature" && newval>5000) - tlv.vars[varname] = 5000 - else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) - tlv.vars[varname] = 50*ONE_ATMOSPHERE - else if (env!="temperature" && env!="pressure" && newval>200) - tlv.vars[varname] = 200 - else - newval = round(newval,0.01) - tlv.vars[varname] = newval - - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - - if(href_list["atmos_alarm"]) - if (alarm_area.atmosalert(2,src)) - post_alert(2) - update_icon() - - if(href_list["atmos_reset"]) - if (alarm_area.atmosalert(0,src)) - post_alert(0) - update_icon() - - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() + switch(action) + if("toggleaccess") + if(usr.has_unlimited_silicon_privilege && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) + locked = !locked + if("adjust") + var/device_id = params["id_tag"] + switch(params["command"]) + if("set_external_pressure") + var/input_pressure = input("Enter target pressure:", "Pressure Controls") as num|null + if(isnum(input_pressure)) + send_signal(device_id, list(params["command"] = input_pressure)) + if("reset_external_pressure") + send_signal(device_id, list("set_external_pressure" = ONE_ATMOSPHERE)) + if( + "power", + "adjust_external_pressure", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "widenet", + "scrubbing" + ) + send_signal(device_id, list (params["command"] = text2num(params["val"]))) + if ("excheck") + send_signal(device_id, list ("checks" = text2num(params["val"])^1)) + if ("incheck") + send_signal(device_id, list ("checks" = text2num(params["val"])^2)) + if("set_threshold") + var/env = params["env"] + var/varname = params["var"] + var/datum/tlv/tlv = TLV[env] + var/newval = input("Enter [varname] for [env]:", "Alarm Triggers", tlv.vars[varname]) as num|null + if (isnull(newval)) + return + if (newval<0) + tlv.vars[varname] = -1 + else if (env=="temperature" && newval>5000) + tlv.vars[varname] = 5000 + else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) + tlv.vars[varname] = 50*ONE_ATMOSPHERE + else if (env!="temperature" && env!="pressure" && newval>200) + tlv.vars[varname] = 200 + else + newval = round(newval,0.01) + tlv.vars[varname] = newval + if("screen") + screen = text2num(params["screen"]) + if("mode") + mode = text2num(params["mode"]) + apply_mode() + if("alarm") + if(alarm_area.atmosalert(2, src)) + post_alert(2) + update_icon() + if("reset") + if(alarm_area.atmosalert(0, src)) + post_alert(0) + update_icon() + return 1 /obj/machinery/alarm/proc/apply_mode() switch(mode) diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 3e36bf39410..f201c663091 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -271,13 +271,12 @@ update_flag /obj/machinery/portable_atmospherics/canister/interact(mob/user) if (src.destroyed) return - add_fingerprint(user) ui_interact(user) /obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "canister.tmpl", name, 470, 400, state = physical_state) + ui = new(user, src, ui_key, "canister", name, 470, 470, state = physical_state) ui.open() /obj/machinery/portable_atmospherics/canister/get_ui_data() @@ -299,71 +298,71 @@ update_flag data["holdingTank"]["tankPressure"] = round(holding.air_contents.return_pressure()) return data -/obj/machinery/portable_atmospherics/canister/Topic(href, href_list) +/obj/machinery/portable_atmospherics/canister/ui_act(action, params) if(..()) return - if(href_list["toggle"]) - var/logmsg - if (valve_open) - if (holding) - logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the [holding]
" - else - logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the air
" - else - if (holding) - logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the [holding]
" - else - logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the air
" - if(air_contents.toxins > 0) - message_admins("[key_name_admin(usr)] (?) (FLW) opened a canister that contains plasma! (JMP)") - log_admin("[key_name(usr)] opened a canister that contains plasma at [x], [y], [z]") - var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air_contents.trace_gases - if(sleeping_agent && (sleeping_agent.moles > 1)) - message_admins("[key_name_admin(usr)] (?) (FLW) opened a canister that contains N2O! (JMP)") - log_admin("[key_name(usr)] opened a canister that contains N2O at [x], [y], [z]") - investigate_log(logmsg, "atmos") - release_log += logmsg - valve_open = !valve_open - if (href_list["remove_tank"]) - if(holding) + switch(action) + if("relabel") + if (can_label) + var/list/colors = list(\ + "\[N2O\]" = "redws", \ + "\[N2\]" = "red", \ + "\[O2\]" = "blue", \ + "\[Plasma\]" = "orange", \ + "\[CO2\]" = "black", \ + "\[Air\]" = "grey", \ + "\[CAUTION\]" = "yellow", \ + ) + var/label = input("Label canister:", "Gas Canister") as null|anything in colors + if(label) + src.canister_color = colors[label] + src.icon_state = colors[label] + src.name = "canister: [label]" + if("pressure") + switch(params["set"]) + if("custom") + var/custom = input(usr, "What rate do you set the regulator to? The dial reads from [CAN_MIN_RELEASE_PRESSURE] to [CAN_MAX_RELEASE_PRESSURE].") as null|num + if(custom) + release_pressure = custom + if("reset") + release_pressure = CAN_DEFAULT_RELEASE_PRESSURE + if("min") + release_pressure = CAN_MIN_RELEASE_PRESSURE + if("max") + release_pressure = CAN_MAX_RELEASE_PRESSURE + release_pressure = Clamp(round(release_pressure), CAN_MIN_RELEASE_PRESSURE, CAN_MAX_RELEASE_PRESSURE) + if("valve") + var/logmsg if (valve_open) - investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transfering into the air
", "atmos") - holding.loc = loc - holding = null - if (href_list["release_p"]) - if (href_list["release_p"] == "custom") - var/custom = input(usr, "What rate do you set the regulator to? The dial reads from [CAN_MIN_RELEASE_PRESSURE] to [CAN_MAX_RELEASE_PRESSURE].") as null|num - if(isnum(custom)) - href_list["release_p"] = custom - .() - else if (href_list["release_p"] == "reset") - release_pressure = CAN_DEFAULT_RELEASE_PRESSURE - else if (href_list["release_p"] == "min") - release_pressure = CAN_MIN_RELEASE_PRESSURE - else if (href_list["release_p"] == "max") - release_pressure = CAN_MAX_RELEASE_PRESSURE - else - release_pressure = text2num(href_list["release_p"]) - release_pressure = min(max(round(release_pressure), CAN_MIN_RELEASE_PRESSURE), CAN_MAX_RELEASE_PRESSURE) - if (href_list["relabel"]) - if (can_label) - var/list/colors = list(\ - "\[N2O\]" = "redws", \ - "\[N2\]" = "red", \ - "\[O2\]" = "blue", \ - "\[Plasma\]" = "orange", \ - "\[CO2\]" = "black", \ - "\[Air\]" = "grey", \ - "\[CAUTION\]" = "yellow", \ - ) - var/label = input("Choose canister label", "Gas canister") as null|anything in colors - if (label) - src.canister_color = colors[label] - src.icon_state = colors[label] - src.name = "canister: [label]" - + if (holding) + logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the [holding]
" + else + logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the air
" + else + if (holding) + logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the [holding]
" + else + logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the air
" + if(air_contents.toxins > 0) + message_admins("[key_name_admin(usr)] (?) (FLW) opened a canister that contains plasma! (JMP)") + log_admin("[key_name(usr)] opened a canister that contains plasma at [x], [y], [z]") + var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air_contents.trace_gases + if(sleeping_agent && (sleeping_agent.moles > 1)) + message_admins("[key_name_admin(usr)] (?) (FLW) opened a canister that contains N2O! (JMP)") + log_admin("[key_name(usr)] opened a canister that contains N2O at [x], [y], [z]") + investigate_log(logmsg, "atmos") + release_log += logmsg + valve_open = !valve_open + if("eject") + if(holding) + if (valve_open) + investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transfering into the air
", "atmos") + holding.loc = loc + holding = null + add_fingerprint(usr) update_icon() + return 1 /obj/machinery/portable_atmospherics/canister/toxins/New() ..() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 9257aad65c2..9528ce6311b 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -203,6 +203,8 @@ for(var/mob/O in player_list) if(istype(O, /mob/living/silicon/ai)) var/mob/living/silicon/ai/AI = O + if(AI.control_disabled || (AI.stat == DEAD)) + return if(U.name == "Unknown") AI << "[U] holds \a [itemname] up to one of your cameras ..." else diff --git a/code/game/machinery/computer/syndicate_shuttle.dm b/code/game/machinery/computer/syndicate_shuttle.dm index 7dee81f1c6b..2f397908c84 100644 --- a/code/game/machinery/computer/syndicate_shuttle.dm +++ b/code/game/machinery/computer/syndicate_shuttle.dm @@ -1,3 +1,5 @@ +#define SYNDICATE_CHALLENGE_TIMER 12000 //20 minutes + /obj/machinery/computer/shuttle/syndicate name = "syndicate shuttle terminal" icon_screen = "syndishuttle" @@ -5,7 +7,18 @@ req_access = list(access_syndicate) shuttleId = "syndicate" possible_destinations = "syndicate_away;syndicate_z5;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s" + var/challenge = FALSE /obj/machinery/computer/shuttle/syndicate/recall name = "syndicate shuttle recall terminal" possible_destinations = "syndicate_away" + + +/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list) + if(href_list["move"]) + if(challenge && world.time < SYNDICATE_CHALLENGE_TIMER) + usr << "You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare." + return 0 + ..() + +#undef SYNDICATE_CHALLENGE_TIMER \ No newline at end of file diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 63bce544e72..59e312eaf45 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -16,7 +16,7 @@ /obj/item/weapon/electronics/airlock/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0) SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "airlock_electronics.tmpl", name, 975, 415, state = hands_state) + ui = new(user, src, ui_key, "airlock_electronics", name, 975, 415, state = hands_state) ui.open() /obj/item/weapon/electronics/airlock/get_ui_data() @@ -40,19 +40,20 @@ return data -/obj/item/weapon/electronics/airlock/Topic(href, href_list) +/obj/item/weapon/electronics/airlock/ui_act(action, params) if(..()) return - if(href_list["access"]) - if(href_list["access"] == "clear") + switch(action) + if("clear") accesses = list() one_access = 0 - else if(href_list["access"] == "one") + if("one_access") one_access = !one_access - else - var/access = text2num(href_list["access"]) + if("set") + var/access = text2num(params["access"]) if (!(access in accesses)) accesses += access else accesses -= access + return 1 diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index a9855999280..852f62ffeca 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -108,6 +108,12 @@ doortype = /obj/structure/door_assembly/door_assembly_viro/glass glass = 1 +/obj/machinery/door/airlock/glass_maintenance + icon = 'icons/obj/doors/airlocks/station/maintenance.dmi' + opacity = 0 + doortype = /obj/structure/door_assembly/door_assembly_mai/glass + glass = 1 + ////////////////////////////////// /* Station Airlocks Mineral @@ -216,6 +222,14 @@ overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' doortype = /obj/structure/door_assembly/door_assembly_ext +/obj/machinery/door/airlock/glass_external + name = "external airlock" + icon = 'icons/obj/doors/airlocks/external/external.dmi' + overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' + doortype = /obj/structure/door_assembly/door_assembly_ext/glass + opacity = 0 + glass = 1 + ////////////////////////////////// /* Centcom Airlocks diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index fede733c2af..7f081902b51 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -209,6 +209,13 @@ Class Procs: add_fingerprint(usr) return 0 +/obj/machinery/ui_act(action, params) + ..() + if(!can_be_used_by(usr)) + return 1 + add_fingerprint(usr) + return 0 + /obj/machinery/proc/can_be_used_by(mob/user) if(!interact_offline && stat & (NOPOWER|BROKEN)) return 0 diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 737d22ee22d..d5e58202f1c 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -159,65 +159,57 @@ /obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "space_heater.tmpl", name, 490, 350, state = physical_state) + ui = new(user, src, ui_key, "space_heater", name, 490, 340, state = physical_state) ui.open() -/obj/machinery/space_heater/Topic(href, href_list) - if((stat & BROKEN) || ..()) +/obj/machinery/space_heater/ui_act(action, params) + if(..()) return - add_fingerprint(usr) + switch(action) + if("power") + on = !on + mode = HEATER_MODE_STANDBY + usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "You switch [on ? "on" : "off"] \the [src].") + update_icon() + if("mode") + setMode = params["mode"] + if("temp") + if(panel_open) + var/value + if(params["set"] == "custom") + value = input("Please input the target temperature", name) as num|null + if(isnull(value)) + return + value += T0C + else + value = targetTemperature + text2num(params["set"]) - if(href_list["power"]) - on = !!text2num(href_list["power"]) - mode = HEATER_MODE_STANDBY - usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "You switch [on ? "on" : "off"] \the [src].") - update_icon() - SSnano.update_uis(src) - - else if(href_list["mode"]) - setMode = href_list["mode"] - SSnano.update_uis(src) - - else if(href_list["temp"] && panel_open) - var/value - if(href_list["temp"] == "custom") - value = input("Please input the target temperature", name) as num|null - if(isnull(value)) - return - value += T0C - else - value = targetTemperature + text2num(href_list["temp"]) - - var/minTemp = max(settableTemperatureMedian - settableTemperatureRange, TCMB) - var/maxTemp = settableTemperatureMedian + settableTemperatureRange - targetTemperature = dd_range(minTemp, maxTemp, round(value, 1)) - SSnano.update_uis(src) - - else if(href_list["cellremove"] && panel_open) - if(cell) - if(usr.get_active_hand()) - usr << "You need an empty hand to remove \the [cell]!" - return - cell.updateicon() - usr.put_in_hands(cell) - cell.add_fingerprint(usr) - usr.visible_message("\The [usr] removes \the [cell] from \the [src].", "You remove \the [cell] from \the [src].") - cell = null - SSnano.update_uis(src) - - else if(href_list["cellinstall"] && panel_open) - if(!cell) - var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand() - if(istype(C)) - if(!usr.drop_item()) + var/minTemp = max(settableTemperatureMedian - settableTemperatureRange, TCMB) + var/maxTemp = settableTemperatureMedian + settableTemperatureRange + targetTemperature = dd_range(minTemp, maxTemp, round(value, 1)) + if("ejectcell") + if(panel_open && cell) + if(usr.get_active_hand()) + usr << "You need an empty hand to remove \the [cell]!" return - cell = C - C.loc = src - C.add_fingerprint(usr) - - usr.visible_message("\The [usr] inserts \a [C] into \the [src].", "You insert \the [C] into \the [src].") - SSnano.update_uis(src) + cell.updateicon() + usr.put_in_hands(cell) + cell.add_fingerprint(usr) + usr.visible_message("\The [usr] removes \the [cell] from \the [src].", "You remove \the [cell] from \the [src].") + cell = null + if("installcell") + if(panel_open && !cell) + var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand() + if(istype(C)) + if(!usr.drop_item()) + return + cell = C + C.loc = src + C.add_fingerprint(usr) + usr.visible_message("\The [usr] inserts \a [C] into \the [src].", "You insert \the [C] into \the [src].") + add_fingerprint(usr) + return 1 /obj/machinery/space_heater/process() if(!on || (stat & BROKEN)) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index c4ce6fa4612..9d5169e5781 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -254,9 +254,12 @@ if(newfreq && canAccess(usr)) if(findtext(num2text(newfreq), ".")) newfreq *= 10 // shift the decimal one place - if(!(newfreq in freq_listening) && newfreq < 10000) - freq_listening.Add(newfreq) - temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-" + if(newfreq == SYND_FREQ) + temp = "-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-" + else + if(!(newfreq in freq_listening) && newfreq < 10000) + freq_listening.Add(newfreq) + temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-" if(href_list["delete"]) diff --git a/code/game/machinery/telecomms/machines/bus.dm b/code/game/machinery/telecomms/machines/bus.dm index c81ecec4b32..7b747d4d332 100644 --- a/code/game/machinery/telecomms/machines/bus.dm +++ b/code/game/machinery/telecomms/machines/bus.dm @@ -26,7 +26,8 @@ if(is_freq_listening(signal)) if(change_frequency) - signal.frequency = change_frequency + if(signal.frequency != SYND_FREQ) + signal.frequency = change_frequency if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it // send to one linked processor unit diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index b88cc1e0923..ecaecfae372 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -287,6 +287,8 @@ return power_station /obj/machinery/teleport/hub/Bumped(M as mob|obj) + if(z == ZLEVEL_CENTCOM) + M << "You can't use this here." if(power_station && power_station.engaged && !panel_open) teleport(M) use_power(5000) diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 8d94ed2e15e..07231ed8854 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -118,12 +118,13 @@ var/obj/mecha/working/mecha = loc if(!mecha.occupant) return + var/mob/pilot = mecha.occupant var/list/occupant = list() - occupant |= mecha.occupant - mecha.occupant.sight |= SEE_TURFS + occupant |= pilot + pilot.sight |= SEE_TURFS scanning = 1 mineral_scan_pulse(occupant,get_turf(loc)) spawn(equip_cooldown) scanning = 0 - mecha.occupant.sight -= SEE_TURFS + pilot.sight -= SEE_TURFS diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 4613228ec11..06f2122fc3c 100755 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1255,6 +1255,7 @@ icon_state = "nuketoy" var/cooldown = 0 var/toysay = "What the fuck did you do?" + var/toysound = 'sound/machines/click.ogg' /obj/item/toy/figure/New() desc = "A \"Space Life\" brand [src]." @@ -1263,7 +1264,7 @@ if(cooldown <= world.time) cooldown = world.time + 50 user << "The [src] says \"[toysay]\"" - playsound(user, 'sound/machines/click.ogg', 20, 1) + playsound(user, toysound, 20, 1) /obj/item/toy/figure/cmo name = "Chief Medical Officer action figure" @@ -1289,6 +1290,7 @@ name = "Cyborg action figure" icon_state = "borg" toysay = "I. LIVE. AGAIN." + toysound = 'sound/voice/liveagain.ogg' /obj/item/toy/figure/botanist name = "Botanist action figure" @@ -1329,6 +1331,7 @@ name = "Clown action figure" icon_state = "clown" toysay = "Honk!" + toysound = 'sound/items/bikehorn.ogg' /obj/item/toy/figure/ian name = "Ian action figure" @@ -1394,6 +1397,7 @@ name = "Mime action figure" icon_state = "mime" toysay = "..." + toysound = null /obj/item/toy/figure/miner name = "Shaft Miner action figure" @@ -1409,6 +1413,7 @@ name = "Wizard action figure" icon_state = "wizard" toysay = "Ei Nath!" + toysound = 'sound/magic/Disintegrate.ogg' /obj/item/toy/figure/rd name = "Research Director action figure" @@ -1419,11 +1424,13 @@ name = "Roboticist action figure" icon_state = "roboticist" toysay = "Big stompy mechs!" + toysound = 'sound/mecha/mechstep.ogg' /obj/item/toy/figure/scientist name = "Scientist action figure" icon_state = "scientist" toysay = "For science!" + toysound = 'sound/effects/explosionfar.ogg' /obj/item/toy/figure/syndie name = "Nuclear Operative action figure" @@ -1434,6 +1441,7 @@ name = "Security Officer action figure" icon_state = "secofficer" toysay = "I am the law!" + toysound = 'sound/voice/complionator/dredd.ogg' /obj/item/toy/figure/virologist name = "Virologist action figure" diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 793948a60ff..bde9fa7fa01 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -63,7 +63,7 @@ /obj/item/clothing/head/snowman) gift_type_list += subtypesof(/obj/item/clothing/head/collectable) - gift_type_list += subtypesof(/obj/item/toy) - (((typesof(/obj/item/toy/cards) - /obj/item/toy/cards/deck) + /obj/item/toy/ammo)) //All toys, except for abstract types and syndicate cards. + gift_type_list += subtypesof(/obj/item/toy) - (((typesof(/obj/item/toy/cards) - /obj/item/toy/cards/deck) + /obj/item/toy/figure + /obj/item/toy/ammo)) //All toys, except for abstract types and syndicate cards. var/gift_type = pick(gift_type_list) diff --git a/code/game/objects/items/weapons/storage/book.dm b/code/game/objects/items/weapons/storage/book.dm index d3f66253707..22c4aeca93d 100644 --- a/code/game/objects/items/weapons/storage/book.dm +++ b/code/game/objects/items/weapons/storage/book.dm @@ -146,17 +146,10 @@ var/global/list/bibleitemstates = list("bible", "koran", "scrapbook", "bible", " user.Paralyse(20) return -// if(..() == BLOCKED) -// return - if (M.stat !=2) if(M.mind && (M.mind.assigned_role == "Chaplain")) user << "You can't heal yourself!" return - /*if((M.mind in ticker.mode.cult) && (prob(20))) - M << "\red The power of [src.deity_name] clears your mind of heresy!" - user << "\red You see how [M]'s eyes become clear, the cult no longer holds control over him!" - ticker.mode.remove_cultist(M.mind)*/ if ((istype(M, /mob/living/carbon/human) && prob(60))) bless(M) if(ishuman(M)) diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index ac41c83c18c..5a8bb1245ff 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -122,7 +122,7 @@ /obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0) ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open) if (!ui) - ui = new(user, src, ui_key, "tanks.tmpl", name, 525, 175, state = inventory_state) + ui = new(user, src, ui_key, "tanks", name, 525, 210, state = inventory_state) ui.open() /obj/item/weapon/tank/get_ui_data() @@ -157,42 +157,43 @@ data["maskConnected"] = 1 return data -/obj/item/weapon/tank/Topic(href, href_list) +/obj/item/weapon/tank/ui_act(action, params) if (..()) return - if (href_list["dist_p"]) - if (href_list["dist_p"] == "custom") - var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num - if(isnum(custom)) - href_list["dist_p"] = custom - .() - else if (href_list["dist_p"] == "reset") - distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - else if (href_list["dist_p"] == "min") - distribute_pressure = TANK_MIN_RELEASE_PRESSURE - else if (href_list["dist_p"] == "max") - distribute_pressure = TANK_MAX_RELEASE_PRESSURE - else - distribute_pressure = text2num(href_list["dist_p"]) - distribute_pressure = min(max(round(distribute_pressure), TANK_MIN_RELEASE_PRESSURE), TANK_MAX_RELEASE_PRESSURE) - if (href_list["stat"]) - if(istype(loc,/mob/living/carbon)) - var/mob/living/carbon/location = loc - if(location.internal == src) - location.internal = null - location.internals.icon_state = "internal0" - usr << "You close the tank release valve." - if (location.internals) + switch(action) + if("pressure") + switch(params["set"]) + if("custom") + var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num + if(isnum(custom)) + distribute_pressure = custom + if("reset") + distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE + if("min") + distribute_pressure = TANK_MIN_RELEASE_PRESSURE + if("max") + distribute_pressure = TANK_MAX_RELEASE_PRESSURE + distribute_pressure = Clamp(round(distribute_pressure), TANK_MIN_RELEASE_PRESSURE, TANK_MAX_RELEASE_PRESSURE) + if("valve") + if(istype(loc,/mob/living/carbon)) + var/mob/living/carbon/location = loc + if(location.internal == src) + location.internal = null location.internals.icon_state = "internal0" - else - if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS)) - location.internal = src - usr << "You open \the [src] valve." + usr << "You close the tank release valve." if (location.internals) - location.internals.icon_state = "internal1" + location.internals.icon_state = "internal0" else - usr << "You need something to connect to \the [src]!" + if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS)) + location.internal = src + usr << "You open \the [src] valve." + if (location.internals) + location.internals.icon_state = "internal1" + else + usr << "You need something to connect to \the [src]!" + return 1 + /obj/item/weapon/tank/remove_air(amount) return air_contents.remove(amount) diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index f48b7f6e9b1..889d629d926 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -235,7 +235,7 @@ spawn(0) for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2)) user.dir = i - if(prob(20)) + if(i == 8) user.emote("flip") sleep(1) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index aed76f2b6dc..2054d013079 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -142,20 +142,30 @@ icon = 'icons/obj/doors/airlocks/station/maintenance.dmi' typetext = "maintenance" icontext = "mai" + glass_type = /obj/machinery/door/airlock/glass_maintenance airlock_type = /obj/machinery/door/airlock/maintenance anchored = 1 state = 1 +/obj/structure/door_assembly/door_assembly_mai/glass + mineral = "glass" + material = "glass" + /obj/structure/door_assembly/door_assembly_ext name = "external airlock assembly" icon = 'icons/obj/doors/airlocks/external/external.dmi' overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' typetext = "external" icontext = "ext" + glass_type = /obj/machinery/door/airlock/glass_external airlock_type = /obj/machinery/door/airlock/external anchored = 1 state = 1 +/obj/structure/door_assembly/door_assembly_ext/glass + mineral = "glass" + material = "glass" + /obj/structure/door_assembly/door_assembly_fre name = "freezer airlock assembly" icon = 'icons/obj/doors/airlocks/station/freezer.dmi' diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 215a52c08bd..ab4bac63354 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -214,8 +214,9 @@ else if (istype(AM, /mob/living)) var/mob/living/L = AM L.adjustFireLoss(20) - L.adjust_fire_stacks(20) - L.IgniteMob() + if(L) //mobs turning into object corpses could get deleted here. + L.adjust_fire_stacks(20) + L.IgniteMob() /turf/simulated/floor/plating/lava/attackby(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 07881623118..bfb2d195477 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -272,8 +272,7 @@ var/list/admin_verbs_hideable = list( /client/proc/fps, /client/proc/cmd_admin_grantfullaccess, /client/proc/cmd_admin_areatest, - /client/proc/readmin, - /client/proc/reload_nanoui_resources + /client/proc/readmin ) if(holder) verbs.Remove(holder.rank.adds) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index e6dd19001ae..02de8309c59 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -310,97 +310,6 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that else alert("Invalid mob") -/* -/client/proc/cmd_admin_monkeyize(var/mob/M in world) - set category = "Fun" - set name = "Make Monkey" - - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/target = M - log_admin("[key_name(src)] is attempting to monkeyize [M.key].") - spawn(10) - target.monkeyize() - else - alert("Invalid mob") - -/client/proc/cmd_admin_changelinginize(var/mob/M in world) - set category = "Fun" - set name = "Make Changeling" - - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon/human)) - log_admin("[key_name(src)] has made [M.key] a changeling.") - spawn(10) - M.absorbed_dna[M.real_name] = M.dna - M.make_changeling() - if(M.mind) - M.mind.special_role = "Changeling" - else - alert("Invalid mob") -*/ -/* -/client/proc/cmd_admin_abominize(var/mob/M in world) - set category = null - set name = "Make Abomination" - - usr << "Ruby Mode disabled. Command aborted." - return - if(!ticker) - alert("Wait until the game starts.") - return - if(istype(M, /mob/living/carbon/human)) - log_admin("[key_name(src)] has made [M.key] an abomination.") - - // spawn(10) - // M.make_abomination() - -*/ -/* -/client/proc/make_cultist(var/mob/M in world) - set category = "Fun" - set name = "Make Cultist" - set desc = "Makes target a cultist" - if(!wordtravel) - runerandom() - if(M) - if(M.mind in ticker.mode.cult) - return - else - if(alert("Spawn that person a tome?",,"Yes","No")=="Yes") - M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie. A tome, a message from your new master, appears on the ground." - new /obj/item/weapon/tome(M.loc) - else - M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." - var/glimpse=pick("1","2","3","4","5","6","7","8") - switch(glimpse) - if("1") - M << "\red You remembered one thing from the glimpse... [wordtravel] is travel..." - if("2") - M << "\red You remembered one thing from the glimpse... [wordblood] is blood..." - if("3") - M << "\red You remembered one thing from the glimpse... [wordjoin] is join..." - if("4") - M << "\red You remembered one thing from the glimpse... [wordhell] is Hell..." - if("5") - M << "\red You remembered one thing from the glimpse... [worddestr] is destroy..." - if("6") - M << "\red You remembered one thing from the glimpse... [wordtech] is technology..." - if("7") - M << "\red You remembered one thing from the glimpse... [wordself] is self..." - if("8") - M << "\red You remembered one thing from the glimpse... [wordsee] is see..." - - if(M.mind) - M.mind.special_role = "Cultist" - ticker.mode.cult += M.mind - src << "Made [M] a cultist." -*/ - var/list/TYPES_SHORTCUTS = list( /obj/effect/decal/cleanable = "CLEANABLE", /obj/item/device/radio/headset = "HEADSET", @@ -776,18 +685,3 @@ var/global/list/g_fancy_list_of_types = null if(!holder) return debug_variables(huds[i]) - -/client/proc/reload_nanoui_resources() - set category = "Debug" - set name = "Reload NanoUI Resources" - set desc = "Force the client to redownload NanoUI Resources" - - // Close open NanoUIs. - SSnano.close_user_uis(usr) - - // Re-load the assets. - var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui) - assets.register() - - // Clear the user's cache so they get resent. - usr.client.cache = list() diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index ad7d2574683..122e85d711f 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -159,7 +159,6 @@ var/intercom_range_display_status = 0 src.verbs += /client/proc/cmd_show_at_list src.verbs += /client/proc/cmd_show_at_list src.verbs += /client/proc/manipulate_organs - src.verbs += /client/proc/reload_nanoui_resources feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index c60bcca1fc3..be7c7f7c7cb 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -194,7 +194,6 @@ /datum/admins/proc/makeCult() - var/datum/game_mode/cult/temp = new if(config.protect_roles_from_antagonist) temp.restricted_jobs += temp.protected_jobs @@ -216,7 +215,7 @@ candidates += applicant if(candidates.len) - var/numCultists = min(candidates.len, 4) + var/numCultists = min(candidates.len, 5) for(var/i = 0, i - window.location.href="?asset_cache_confirm_arrival=[job]" - - "}, "window=asset_cache_browser") - - var/t = 0 - var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT - while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() - sleep(1) // Lock up the caller until this is received. - t++ - - if(client) - client.sending -= asset_name - client.cache |= asset_name - client.completed_asset_jobs -= job - - return 1 - -//This proc blocks(sleeps) unless verify is set to false -/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE) - if(!istype(client)) - if(ismob(client)) - var/mob/M = client - if(M.client) - client = M.client - - else - return 0 - - else - return 0 - - var/list/unreceived = asset_list - (client.cache + client.sending) - if(!unreceived || !unreceived.len) - return 0 - if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT) - client << "Sending Resources..." - for(var/asset in unreceived) - if (asset in SSasset.cache) - client << browse_rsc(SSasset.cache[asset], asset) - - if(!verify || !winexists(client, "asset_cache_browser")) // Can't access the asset cache browser, rip. - if (client) - client.cache += unreceived - return 1 - if (!client) - return 0 - client.sending |= unreceived - var/job = ++client.last_asset_job - - client << browse({" - - "}, "window=asset_cache_browser") - - var/t = 0 - var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len - while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() - sleep(1) // Lock up the caller until this is received. - t++ - - if(client) - client.sending -= unreceived - client.cache |= unreceived - client.completed_asset_jobs -= job - - return 1 - -//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start. -//The proc calls procs that sleep for long times. -/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) - for(var/file in files) - if (!client) - break - if (register_asset) - register_asset(file,files[file]) - send_asset(client,file) - sleep(-1) //queuing calls like this too quickly can cause issues in some client versions - -//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up. -//if it's an icon or something be careful, you'll have to copy it before further use. -/proc/register_asset(var/asset_name, var/asset) - SSasset.cache[asset_name] = asset - -//These datums are used to populate the asset cache, the proc "register()" does this. - -//all of our asset datums, used for referring to these later -/var/global/list/asset_datums = list() - -//get a assetdatum or make a new one -/proc/get_asset_datum(var/type) - if (!(type in asset_datums)) - return new type() - return asset_datums[type] - -/datum/asset/New() - asset_datums[type] = src - -/datum/asset/proc/register() - return - -/datum/asset/proc/send(client) - return - -//If you don't need anything complicated. -/datum/asset/simple - var/assets = list() - var/verify = FALSE - -/datum/asset/simple/register() - for(var/asset_name in assets) - register_asset(asset_name, assets[asset_name]) -/datum/asset/simple/send(client) - send_asset_list(client,assets,verify) - - -//DEFINITIONS FOR ASSET DATUMS START HERE. - - -/datum/asset/simple/pda - assets = list( - "pda_atmos.png" = 'icons/pda_icons/pda_atmos.png', - "pda_back.png" = 'icons/pda_icons/pda_back.png', - "pda_bell.png" = 'icons/pda_icons/pda_bell.png', - "pda_blank.png" = 'icons/pda_icons/pda_blank.png', - "pda_boom.png" = 'icons/pda_icons/pda_boom.png', - "pda_bucket.png" = 'icons/pda_icons/pda_bucket.png', - "pda_medbot.png" = 'icons/pda_icons/pda_medbot.png', - "pda_floorbot.png" = 'icons/pda_icons/pda_floorbot.png', - "pda_cleanbot.png" = 'icons/pda_icons/pda_cleanbot.png', - "pda_crate.png" = 'icons/pda_icons/pda_crate.png', - "pda_cuffs.png" = 'icons/pda_icons/pda_cuffs.png', - "pda_eject.png" = 'icons/pda_icons/pda_eject.png', - "pda_exit.png" = 'icons/pda_icons/pda_exit.png', - "pda_flashlight.png" = 'icons/pda_icons/pda_flashlight.png', - "pda_honk.png" = 'icons/pda_icons/pda_honk.png', - "pda_mail.png" = 'icons/pda_icons/pda_mail.png', - "pda_medical.png" = 'icons/pda_icons/pda_medical.png', - "pda_menu.png" = 'icons/pda_icons/pda_menu.png', - "pda_mule.png" = 'icons/pda_icons/pda_mule.png', - "pda_notes.png" = 'icons/pda_icons/pda_notes.png', - "pda_power.png" = 'icons/pda_icons/pda_power.png', - "pda_rdoor.png" = 'icons/pda_icons/pda_rdoor.png', - "pda_reagent.png" = 'icons/pda_icons/pda_reagent.png', - "pda_refresh.png" = 'icons/pda_icons/pda_refresh.png', - "pda_scanner.png" = 'icons/pda_icons/pda_scanner.png', - "pda_signaler.png" = 'icons/pda_icons/pda_signaler.png', - "pda_status.png" = 'icons/pda_icons/pda_status.png' - ) - -/datum/asset/simple/paper - assets = list( - "large_stamp-clown.png" = 'icons/stamp_icons/large_stamp-clown.png', - "large_stamp-deny.png" = 'icons/stamp_icons/large_stamp-deny.png', - "large_stamp-ok.png" = 'icons/stamp_icons/large_stamp-ok.png', - "large_stamp-hop.png" = 'icons/stamp_icons/large_stamp-hop.png', - "large_stamp-cmo.png" = 'icons/stamp_icons/large_stamp-cmo.png', - "large_stamp-ce.png" = 'icons/stamp_icons/large_stamp-ce.png', - "large_stamp-hos.png" = 'icons/stamp_icons/large_stamp-hos.png', - "large_stamp-rd.png" = 'icons/stamp_icons/large_stamp-rd.png', - "large_stamp-cap.png" = 'icons/stamp_icons/large_stamp-cap.png', - "large_stamp-qm.png" = 'icons/stamp_icons/large_stamp-qm.png', - "large_stamp-law.png" = 'icons/stamp_icons/large_stamp-law.png' - ) - -//Registers HTML Interface assets. -/datum/asset/HTML_interface/register() - for(var/path in typesof(/datum/html_interface)) - var/datum/html_interface/hi = new path() - hi.registerResources() - -/datum/asset/nanoui - var/list/common = list() - - var/list/common_dirs = list( - "nano/styles/", - "nano/scripts/", - "nano/images/", - "nano/layouts/" - ) - var/list/uncommon_dirs = list( - "nano/interfaces/" - ) - -/datum/asset/nanoui/register() - // Crawl the directories to find files. - for (var/path in common_dirs) - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename)) != "/") // Ignore directories. - if(fexists(path + filename)) - common[filename] = fcopy_rsc(path + filename) - register_asset(filename, common[filename]) - for (var/path in uncommon_dirs) - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename)) != "/") // Ignore directories. - if(fexists(path + filename)) - register_asset(filename, fcopy_rsc(path + filename)) - -/datum/asset/nanoui/send(client, uncommon) - if(!islist(uncommon)) - uncommon = list(uncommon) - - send_asset_list(client, uncommon) - send_asset_list(client, common) +/* +Asset cache quick users guide: + +Make a datum at the bottom of this file with your assets for your thing. +The simple subsystem will most like be of use for most cases. +Then call get_asset_datum() with the type of the datum you created and store the return +Then call .send(client) on that stored return value. + +You can set verify to TRUE if you want send() to sleep until the client has the assets. +*/ + + +// Amount of time(ds) MAX to send per asset, if this get exceeded we cancel the sleeping. +// This is doubled for the first asset, then added per asset after +#define ASSET_CACHE_SEND_TIMEOUT 7 + +//When sending mutiple assets, how many before we give the client a quaint little sending resources message +#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8 + +/client + var/list/cache = list() // List of all assets sent to this client by the asset cache. + var/list/completed_asset_jobs = list() // List of all completed jobs, awaiting acknowledgement. + var/list/sending = list() + var/last_asset_job = 0 // Last job done. + +//This proc sends the asset to the client, but only if it needs it. +//This proc blocks(sleeps) unless verify is set to false +/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE) + if(!istype(client)) + if(ismob(client)) + var/mob/M = client + if(M.client) + client = M.client + + else + return 0 + + else + return 0 + + if(client.cache.Find(asset_name) || client.sending.Find(asset_name)) + return 0 + + client << browse_rsc(SSasset.cache[asset_name], asset_name) + if(!verify || !winexists(client, "asset_cache_browser")) // Can't access the asset cache browser, rip. + if (client) + client.cache += asset_name + return 1 + if (!client) + return 0 + + client.sending |= asset_name + var/job = ++client.last_asset_job + + client << browse({" + + "}, "window=asset_cache_browser") + + var/t = 0 + var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT + while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() + sleep(1) // Lock up the caller until this is received. + t++ + + if(client) + client.sending -= asset_name + client.cache |= asset_name + client.completed_asset_jobs -= job + + return 1 + +//This proc blocks(sleeps) unless verify is set to false +/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE) + if(!istype(client)) + if(ismob(client)) + var/mob/M = client + if(M.client) + client = M.client + + else + return 0 + + else + return 0 + + var/list/unreceived = asset_list - (client.cache + client.sending) + if(!unreceived || !unreceived.len) + return 0 + if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT) + client << "Sending Resources..." + for(var/asset in unreceived) + if (asset in SSasset.cache) + client << browse_rsc(SSasset.cache[asset], asset) + + if(!verify || !winexists(client, "asset_cache_browser")) // Can't access the asset cache browser, rip. + if (client) + client.cache += unreceived + return 1 + if (!client) + return 0 + client.sending |= unreceived + var/job = ++client.last_asset_job + + client << browse({" + + "}, "window=asset_cache_browser") + + var/t = 0 + var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len + while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() + sleep(1) // Lock up the caller until this is received. + t++ + + if(client) + client.sending -= unreceived + client.cache |= unreceived + client.completed_asset_jobs -= job + + return 1 + +//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start. +//The proc calls procs that sleep for long times. +/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) + for(var/file in files) + if (!client) + break + if (register_asset) + register_asset(file,files[file]) + send_asset(client,file) + sleep(-1) //queuing calls like this too quickly can cause issues in some client versions + +//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up. +//if it's an icon or something be careful, you'll have to copy it before further use. +/proc/register_asset(var/asset_name, var/asset) + SSasset.cache[asset_name] = asset + +//These datums are used to populate the asset cache, the proc "register()" does this. + +//all of our asset datums, used for referring to these later +/var/global/list/asset_datums = list() + +//get a assetdatum or make a new one +/proc/get_asset_datum(var/type) + if (!(type in asset_datums)) + return new type() + return asset_datums[type] + +/datum/asset/New() + asset_datums[type] = src + +/datum/asset/proc/register() + return + +/datum/asset/proc/send(client) + return + +//If you don't need anything complicated. +/datum/asset/simple + var/assets = list() + var/verify = FALSE + +/datum/asset/simple/register() + for(var/asset_name in assets) + register_asset(asset_name, assets[asset_name]) +/datum/asset/simple/send(client) + send_asset_list(client,assets,verify) + + +//DEFINITIONS FOR ASSET DATUMS START HERE. + + +/datum/asset/simple/nanoui + assets = list( + "nanoui.lib.js" = 'nano/assets/nanoui.lib.js', + "nanoui.main.js" = 'nano/assets/nanoui.main.js', + "nanoui.templates.js" = 'nano/assets/nanoui.templates.js', + "nanoui.lib.css" = 'nano/assets/nanoui.lib.css', + "nanoui.common.css" = 'nano/assets/nanoui.common.css', + "nanoui.generic.css" = 'nano/assets/nanoui.generic.css', + "nanoui.nanotrasen.css" = 'nano/assets/nanoui.nanotrasen.css', + "fontawesome-webfont.eot" = 'nano/assets/fontawesome-webfont.eot', + "fontawesome-webfont.woff2" = 'nano/assets/fontawesome-webfont.woff2' + ) + +/datum/asset/simple/pda + assets = list( + "pda_atmos.png" = 'icons/pda_icons/pda_atmos.png', + "pda_back.png" = 'icons/pda_icons/pda_back.png', + "pda_bell.png" = 'icons/pda_icons/pda_bell.png', + "pda_blank.png" = 'icons/pda_icons/pda_blank.png', + "pda_boom.png" = 'icons/pda_icons/pda_boom.png', + "pda_bucket.png" = 'icons/pda_icons/pda_bucket.png', + "pda_medbot.png" = 'icons/pda_icons/pda_medbot.png', + "pda_floorbot.png" = 'icons/pda_icons/pda_floorbot.png', + "pda_cleanbot.png" = 'icons/pda_icons/pda_cleanbot.png', + "pda_crate.png" = 'icons/pda_icons/pda_crate.png', + "pda_cuffs.png" = 'icons/pda_icons/pda_cuffs.png', + "pda_eject.png" = 'icons/pda_icons/pda_eject.png', + "pda_exit.png" = 'icons/pda_icons/pda_exit.png', + "pda_flashlight.png" = 'icons/pda_icons/pda_flashlight.png', + "pda_honk.png" = 'icons/pda_icons/pda_honk.png', + "pda_mail.png" = 'icons/pda_icons/pda_mail.png', + "pda_medical.png" = 'icons/pda_icons/pda_medical.png', + "pda_menu.png" = 'icons/pda_icons/pda_menu.png', + "pda_mule.png" = 'icons/pda_icons/pda_mule.png', + "pda_notes.png" = 'icons/pda_icons/pda_notes.png', + "pda_power.png" = 'icons/pda_icons/pda_power.png', + "pda_rdoor.png" = 'icons/pda_icons/pda_rdoor.png', + "pda_reagent.png" = 'icons/pda_icons/pda_reagent.png', + "pda_refresh.png" = 'icons/pda_icons/pda_refresh.png', + "pda_scanner.png" = 'icons/pda_icons/pda_scanner.png', + "pda_signaler.png" = 'icons/pda_icons/pda_signaler.png', + "pda_status.png" = 'icons/pda_icons/pda_status.png' + ) + +/datum/asset/simple/paper + assets = list( + "large_stamp-clown.png" = 'icons/stamp_icons/large_stamp-clown.png', + "large_stamp-deny.png" = 'icons/stamp_icons/large_stamp-deny.png', + "large_stamp-ok.png" = 'icons/stamp_icons/large_stamp-ok.png', + "large_stamp-hop.png" = 'icons/stamp_icons/large_stamp-hop.png', + "large_stamp-cmo.png" = 'icons/stamp_icons/large_stamp-cmo.png', + "large_stamp-ce.png" = 'icons/stamp_icons/large_stamp-ce.png', + "large_stamp-hos.png" = 'icons/stamp_icons/large_stamp-hos.png', + "large_stamp-rd.png" = 'icons/stamp_icons/large_stamp-rd.png', + "large_stamp-cap.png" = 'icons/stamp_icons/large_stamp-cap.png', + "large_stamp-qm.png" = 'icons/stamp_icons/large_stamp-qm.png', + "large_stamp-law.png" = 'icons/stamp_icons/large_stamp-law.png' + ) + + +//Registers HTML Interface assets. +/datum/asset/HTML_interface/register() + for(var/path in typesof(/datum/html_interface)) + var/datum/html_interface/hi = new path() + hi.registerResources() diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index f05466bf81d..bc8f011ac44 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -22,6 +22,14 @@ /client/Topic(href, href_list, hsrc) if(!usr || usr != mob) //stops us calling Topic for somebody else's client. Also helps prevent usr=null return + // NanoUI + if(href_list["nano_error"]) + src << href_list["nano_error"] + throw EXCEPTION("NanoUI: [href_list["nano_error"]]") + if(href_list["nano_log"]) + src << href_list["nano_log"] + return + // asset_cache if(href_list["asset_cache_confirm_arrival"]) //src << "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED." var/job = text2num(href_list["asset_cache_confirm_arrival"]) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 2f4d81de3a2..9af05edd54f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -27,6 +27,7 @@ var/list/preferences_datums = list() var/UI_style = "Midnight" + var/nanoui_fancy = TRUE var/toggles = TOGGLES_DEFAULT var/chat_toggles = TOGGLES_DEFAULT_CHAT var/ghost_form = "ghost" @@ -321,6 +322,7 @@ var/list/preferences_datums = list() dat += "
" dat += "

General Settings

" dat += "UI Style: [UI_style]
" + dat += "Fancy NanoUI: [(nanoui_fancy) ? "Yes" : "No"]
" dat += "Play admin midis: [(toggles & SOUND_MIDI) ? "Yes" : "No"]
" dat += "Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"]
" dat += "Ghost ears: [(chat_toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
" @@ -1002,6 +1004,9 @@ var/list/preferences_datums = list() else UI_style = "Midnight" + if("nanoui") + nanoui_fancy = !nanoui_fancy + if("hear_adminhelps") toggles ^= SOUND_ADMINHELP if("announce_login") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index e5db8d7ded4..660ebbe3de5 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -165,6 +165,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["ooccolor"] >> ooccolor S["lastchangelog"] >> lastchangelog S["UI_style"] >> UI_style + S["nanoui_fancy"] >> nanoui_fancy S["be_special"] >> be_special if(islist(S["be_special"])) @@ -189,6 +190,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor))) lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) UI_style = sanitize_inlist(UI_style, list("Midnight", "Plasmafire", "Retro"), initial(UI_style)) + nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy)) default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) ghost_form = sanitize_inlist(ghost_form, ghost_forms, initial(ghost_form)) @@ -207,6 +209,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["ooccolor"] << ooccolor S["lastchangelog"] << lastchangelog S["UI_style"] << UI_style + S["nanoui_fancy"] << nanoui_fancy S["be_special"] << be_special S["default_slot"] << default_slot S["toggles"] << toggles diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 0e1b16d75fd..7209b40e937 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -104,7 +104,8 @@ /obj/item/weapon/melee/baton/loaded=1,\ /obj/item/clothing/mask/gas/sechailer=1,\ /obj/item/weapon/gun/energy/gun=1,\ - /obj/item/weapon/reagent_containers/hypospray/combat=1) + /obj/item/weapon/reagent_containers/hypospray/combat=1,\ + /obj/item/weapon/gun/medbeam=1) /datum/outfit/ert/medic/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 377f79b94a5..a9ce46ce9df 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -100,7 +100,7 @@ put_on_delay = 50 /obj/item/clothing/suit/armor/laserproof - name = "ablative armor vest" + name = "reflector vest" desc = "A vest that excels in protecting the wearer against energy projectiles, as well as occasionally reflecting them." icon_state = "armor_reflec" item_state = "armor_reflec" @@ -172,13 +172,13 @@ continue turfs += T if(!turfs.len) - turfs += pick(/turf in orange(6, src)) - var/turf/picked = pick(turfs) - if(!isturf(picked)) - return - if(H.buckled) - H.buckled.unbuckle_mob() - H.forceMove(picked) + turfs += pick(/turf in orange(6, H)) + var/turf/picked = pick(turfs) + if(!isturf(picked)) + return + if(H.buckled) + H.buckled.unbuckle_mob() + H.forceMove(picked) return 1 return 0 diff --git a/code/modules/games/playing_cards.dmi b/code/modules/games/playing_cards.dmi index 47b5b3e745a..ac8916a64e5 100644 Binary files a/code/modules/games/playing_cards.dmi and b/code/modules/games/playing_cards.dmi differ diff --git a/code/modules/html_interface/nanotrasen/nanotrasen.css b/code/modules/html_interface/nanotrasen/hi-nanotrasen.css similarity index 100% rename from code/modules/html_interface/nanotrasen/nanotrasen.css rename to code/modules/html_interface/nanotrasen/hi-nanotrasen.css diff --git a/code/modules/html_interface/nanotrasen/nanotrasen.dm b/code/modules/html_interface/nanotrasen/nanotrasen.dm index 5ae9407093f..0ac9a67a46a 100644 --- a/code/modules/html_interface/nanotrasen/nanotrasen.dm +++ b/code/modules/html_interface/nanotrasen/nanotrasen.dm @@ -18,7 +18,7 @@ The client is optional and may be a /mob, /client or /html_interface_client obje . = ..() // Add appropriate CSS and set the default layout. - src.head = src.head + "" + src.head = src.head + "" src.updateLayout("") /datum/html_interface/nanotrasen/updateLayout(layout) @@ -32,7 +32,7 @@ The client is optional and may be a /mob, /client or /html_interface_client obje /datum/html_interface/nanotrasen/registerResources(var/list/resources = list()) resources["uiBg.png"] = 'uiBg.png' resources["uiBgcenter.png"] = 'uiBgcenter.png' - resources["nanotrasen.css"] = 'nanotrasen.css' + resources["hi-nanotrasen.css"] = 'hi-nanotrasen.css' ..(resources) /datum/html_interface/nanotrasen/createWindow(datum/html_interface_client/hclient) diff --git a/code/modules/json/json.dm b/code/modules/json/json.dm index df6a6a4661c..d3b80d6792d 100644 --- a/code/modules/json/json.dm +++ b/code/modules/json/json.dm @@ -1,12 +1,284 @@ -proc/json2list(json) - var/static/json_reader/_jsonr = new() - return _jsonr.ReadObject(_jsonr.ScanJson(json)) +/* Usage: + JSON.stringify(obj) - Converts lists and values into a JSON string. + JSON.parse(json) - Converts a JSON string into lists and values. +*/ -proc/list2json(list/L) - var/static/json_writer/_jsonw = new() - return _jsonw.write(L) +/var/datum/jsonHelper/JSON = new // A namespace for procs. -proc/list2json_usecache(list/L) - var/static/json_writer/_jsonw = new() - _jsonw.use_cache = 1 - return _jsonw.write(L) \ No newline at end of file +// ************************************ WRITER ************************************ +/datum/jsonHelper/proc/stringify(value) + return list2text(WriteValue(list(), value)) + +/datum/jsonHelper/proc/WriteValue(list/json, value) + . = json + if(isnum(value)) + json += value // Consider num2text(value, 20) for maximum accuracy. + else if(isnull(value)) + json += "null" + else if(istext(value)) + WriteString(json, value) + else if(istype(value, /list)) + WriteList(json, value) + else + throw EXCEPTION("Datums cannot be converted to JSON.") + +/datum/jsonHelper/proc/WriteString(list/json, str) + . = json + var/quotePos = findtextEx(str, "\"") + var/bsPos = findtextEx(str, "\\") + if (quotePos == 0 && bsPos == 0) + json.Add("\"", str, "\"") + else + json += "\"" + var/lastStop = 1 + while(quotePos != 0 || bsPos != 0) + var/escPos + if(quotePos < bsPos && quotePos != 0 || bsPos == 0) + escPos = quotePos + else + escPos = bsPos + json.Add(copytext(str, lastStop, escPos), "\\") + lastStop = escPos + if(escPos == quotePos) + quotePos = findtextEx(str, "\"", escPos + 1) + else if(escPos == bsPos) + bsPos = findtextEx(str, "\\", escPos + 1) + json.Add(copytext(str, lastStop), "\"") + +/datum/jsonHelper/proc/WriteList(list/json, list/listVal) + . = json + #define Either 0 + #define CannotBeArray 1 + #define CannotBeObject 2 + #define BadList (CannotBeArray | CannotBeObject) + var/listType = Either + for(var/key in listVal) + if(istext(key)) + if(!isnull(listVal[key])) + listType |= CannotBeArray + else + if(!isnum(key) && !isnull(listVal[key])) + listType = BadList + else + listType |= CannotBeObject + + if(listType == BadList) + throw EXCEPTION("The given list cannot be converted to JSON.") + + if(listType == CannotBeArray) + json += "{" + var/addComma + for(var/key in listVal) + if(addComma) + json += "," + else + addComma = TRUE + WriteString(json, key) + json += ":" + WriteValue(json, listVal[key]) + json += "}" + else + json += "\[" + var/addComma + for(var/key in listVal) + if(addComma) + json += "," + else + addComma = TRUE + WriteValue(json, key) + json += "]" + #undef Either + #undef CannotBeFlat + #undef CannotBeAssoc + #undef BadList + +// ************************************ READER ************************************ +#define aBackspace 0x08 +#define aTab 0x09 +#define aLineBreak 0x0A +#define aVertTab 0x0B +#define aFormFeed 0x0C +#define aCarriageReturn 0x0D +#define aSpace 0x20 +#define aZero 0x30 +#define aNonBreakSpace 0xA0 + +#define Advance if(++readPos > jsonLen) { curAscii = 0; curChar = "" } else { curAscii = text2ascii(json, readPos); curChar = ascii2text(curAscii) } // Deal with it. +#define SkipWhitespace while(curAscii in whitespace) Advance +#define AdvanceWS Advance; SkipWhitespace + +/datum/jsonHelper/var + readPos + jsonLen + json + curAscii + curChar + static/list/whitespace = list(aTab, aLineBreak, aVertTab, aFormFeed, aCarriageReturn, aSpace, aNonBreakSpace) + +/datum/jsonHelper/proc/parse(json) + readPos = 0 + jsonLen = length(json) + src.json = json + curAscii = 0 + curChar = "" + AdvanceWS + var/value = ParseValue() + if(readPos < jsonLen) + throw EXCEPTION("Expected: End of JSON") + return value + +/datum/jsonHelper/proc/ParseValue() + if(curChar == "\"") + return ParseString() + else if(curChar == "-" || (curAscii >= aZero && curAscii <= aZero + 9)) + return ParseNumber() + else if(curChar == "{") + return ParseObject() + else if(curChar == "\[") + return ParseArray() + else if(curChar == "t") + if(copytext(json, readPos, readPos+4) == "true") + readPos += 3 + AdvanceWS + return TRUE + else + throw EXCEPTION("Expected: 'true'") + else if(curChar == "f") + if(copytext(json, readPos, readPos+5) == "false") + readPos += 4 + AdvanceWS + return FALSE + else + throw EXCEPTION("Expected: 'false'") + else if(curChar == "n") + if(copytext(json, readPos, readPos+4) == "null") + readPos += 3 + AdvanceWS + return null + else + throw EXCEPTION("Expected: 'null'") + else if(curChar == "") + throw EXCEPTION("Unexpected: End of JSON") + else + throw EXCEPTION("Unexpected: '[curChar]'") + + + +/datum/jsonHelper/proc/ParseString() + ASSERT(curChar == "\"") + Advance + var/list/chars = list() + while(readPos <= jsonLen) + if(curChar == "\"") + AdvanceWS + return list2text(chars) + else if(curChar == "\\") + Advance + switch(curChar) + if("\"", "\\", "/") + chars += ascii2text(curAscii) + if("b") + chars += ascii2text(aBackspace) + if("f") + chars += ascii2text(aFormFeed) + if("n") + chars += "\n" + if("r") + chars += ascii2text(aCarriageReturn) // Should we ignore these? + if("t") + chars += "\t" + if("u") + throw EXCEPTION("JSON \\uXXXX escape sequence not supported") + else + throw EXCEPTION("Invalid escape sequence") + Advance + else + chars += ascii2text(curAscii) + Advance + throw EXCEPTION("Unterminated string") + +/datum/jsonHelper/proc/ParseNumber() + var/firstPos = readPos + if(curChar == "-") + Advance + if(curAscii >= aZero + 1 && curAscii <= aZero + 9) + do + Advance + while(curAscii >= aZero && curAscii <= aZero + 9) + else if(curAscii == aZero) + Advance + else + throw EXCEPTION("Expected: digit") + + if(curChar == ".") + Advance + var/found = FALSE + while(curAscii >= aZero && curAscii <= aZero + 9) + found = TRUE + Advance + if(!found) + throw EXCEPTION("Expected: digit") + + if(curChar == "E" || curChar == "e") + Advance + var/found = FALSE + if(curChar == "-") + Advance + else if(curChar == "+") + Advance + while(curAscii >= aZero && curAscii <= aZero + 9) + found = TRUE + Advance + if(!found) + throw EXCEPTION("Expected: digit") + + SkipWhitespace + return text2num(copytext(json, firstPos, readPos)) + +/datum/jsonHelper/proc/ParseObject() + ASSERT(curChar == "{") + var/list/object = list() + AdvanceWS + while(curChar == "\"") + var/key = ParseString() + if(curChar != ":") + throw EXCEPTION("Expected: ':'") + AdvanceWS + object[key] = ParseValue() + if(curChar == ",") + AdvanceWS + else + break + if(curChar != "}") + throw EXCEPTION("Expected: string or '}'") + AdvanceWS + return object + +/datum/jsonHelper/proc/ParseArray() + ASSERT(curChar == "\[") + var/list/array = list() + AdvanceWS + while(curChar != "]") + array += list(ParseValue()) // Wrapped in a list in case ParseValue() returns a list. + if(curChar == ",") + AdvanceWS + else + break + if(curChar != "]") + throw EXCEPTION("Expected: ']'") + AdvanceWS + return array + +#undef aBackspace +#undef aTab +#undef aLineBreak +#undef aVertTab +#undef aFormFeed +#undef aCarriageReturn +#undef aSpace +#undef aZero +#undef aNonBreakSpace + +#undef Advance +#undef SkipWhitespace +#undef AdvanceWS \ No newline at end of file diff --git a/code/modules/json/json_reader.dm b/code/modules/json/json_reader.dm deleted file mode 100644 index 39289201de1..00000000000 --- a/code/modules/json/json_reader.dm +++ /dev/null @@ -1,187 +0,0 @@ -json_reader/var/list/string = list("'", "\"") -json_reader/var/list/symbols = list("{", "}", "\[", "]", ":", "\"", "'", ",") -json_reader/var/list/sequences = list("b" = 8, "t" = 9, "n" = 10, "f" = 12, "r" = 13) -json_reader/var/list/tokens -json_reader/var/json -json_reader/var/i = 1 - - -json_reader/proc/ScanJson(json) - src.json = json - . = new/list() - src.i = 1 - while(src.i <= lentext(json)) - var/char = get_char() - if(is_whitespace(char)) - i++ - continue - if(string.Find(char)) - . += read_string(char) - else if(symbols.Find(char)) - . += new/json_token/symbol(char) - else if(is_digit(char)) - . += read_number() - else - . += read_word() - i++ - . += new/json_token/eof() - -json_reader/proc/read_word() - var/val = "" - while(i <= lentext(json)) - var/char = get_char() - if(is_whitespace(char) || symbols.Find(char)) - i-- // let scanner handle this character - return new/json_token/word(val) - val += char - i++ - -json_reader/proc/read_string(delim) - var/escape = FALSE - var/val = "" - while(++i <= lentext(json)) - var/char = get_char() - if(escape) - switch(char) - if("\\", "'", "\"", "/", "u") - val += char - else - // TODO: support octal, hex, unicode sequences - ASSERT(sequences.Find(char)) - val += ascii2text(sequences[char]) - else - if(char == delim) - return new/json_token/text(val) - else if(char == "\\") - escape = TRUE - else - val += char - CRASH("Unterminated string.") - -json_reader/proc/read_number() - var/val = "" - var/char = get_char() - while(is_digit(char) || char == "." || lowertext(char) == "e") - val += char - i++ - char = get_char() - i-- // allow scanner to read the first non-number character - return new/json_token/number(text2num(val)) - -json_reader/proc/check_char() - ASSERT(args.Find(get_char())) - -json_reader/proc/get_char() - return copytext(json, i, i+1) - -json_reader/proc/is_whitespace(char) - return char == " " || char == "\t" || char == "\n" || text2ascii(char) == 13 - -json_reader/proc/is_digit(char) - var/c = text2ascii(char) - return 48 <= c && c <= 57 || char == "+" || char == "-" - - -json_reader/proc/ReadObject(list/tokens) - src.tokens = tokens - . = new/list() - i = 1 - read_token("{", /json_token/symbol) - while(i <= tokens.len) - var/json_token/K = get_token() - check_type(/json_token/word, /json_token/text) - next_token() - read_token(":", /json_token/symbol) - - .[K.value] = read_value() - - var/json_token/S = get_token() - check_type(/json_token/symbol) - switch(S.value) - if(",") - next_token() - continue - if("}") - next_token() - return - else - die() - -json_reader/proc/get_token() - return tokens[i] - -json_reader/proc/next_token() - return tokens[++i] - -json_reader/proc/read_token(val, type) - var/json_token/T = get_token() - if(!(T.value == val && istype(T, type))) - CRASH("Expected '[val]', found '[T.value]'.") - next_token() - return T - -json_reader/proc/check_type(...) - var/json_token/T = get_token() - for(var/type in args) - if(istype(T, type)) - return - CRASH("Bad token type: [T.type].") - -json_reader/proc/check_value(...) - var/json_token/T = get_token() - ASSERT(args.Find(T.value)) - -json_reader/proc/read_key() - var/char = get_char() - if(char == "\"" || char == "'") - return read_string(char) - -json_reader/proc/read_value() - var/json_token/T = get_token() - switch(T.type) - if(/json_token/text, /json_token/number) - next_token() - return T.value - if(/json_token/word) - next_token() - switch(T.value) - if("true") - return TRUE - if("false") - return FALSE - if("null") - return null - if(/json_token/symbol) - switch(T.value) - if("\[") - return read_array() - if("{") - return ReadObject(tokens.Copy(i)) - die() - -json_reader/proc/read_array() - read_token("\[", /json_token/symbol) - . = new/list() - var/list/L = . - while(i <= tokens.len) - // Avoid using Add() or += in case a list is returned. - L.len++ - L[L.len] = read_value() - var/json_token/T = get_token() - check_type(/json_token/symbol) - switch(T.value) - if(",") - next_token() - continue - if("]") - next_token() - return - else - die() - next_token() - CRASH("Unterminated array.") - - -json_reader/proc/die(json_token/T) - if(!T) T = get_token() - CRASH("Unexpected token: [T.value].") \ No newline at end of file diff --git a/code/modules/json/json_token.dm b/code/modules/json/json_token.dm deleted file mode 100644 index 7344e91b52c..00000000000 --- a/code/modules/json/json_token.dm +++ /dev/null @@ -1,9 +0,0 @@ -json_token/var/value -json_token/New(v) - src.value = v - -json_token/text -json_token/number -json_token/word -json_token/symbol -json_token/eof \ No newline at end of file diff --git a/code/modules/json/json_writer.dm b/code/modules/json/json_writer.dm deleted file mode 100644 index 65c38f3a0a4..00000000000 --- a/code/modules/json/json_writer.dm +++ /dev/null @@ -1,67 +0,0 @@ -#define LIST_FLAT 0 -#define LIST_NESTED 1 -#define LIST_OBJECT 2 // Object in this case means json object, ortherwise known as an associative list or array. - -json_writer/var/use_cache = 0 - -json_writer/proc/write(val) - if(isnum(val)) - . = num2text(val) - else if(isnull(val)) - . = "null" - else if(istype(val, /list)) - switch (listtype(val)) - if (LIST_FLAT) - . = write_array(val) - if (LIST_NESTED) - . = write_array(val) - if (LIST_OBJECT) - . = write_object(val) - else - . = write_string("[val]") - -json_writer/proc/write_object(list/L) - if(use_cache && L["__json_cache"]) - return L["__json_cache"] - . = list() - for(var/k in L) - . += "\"[k]\":[write(L[k])]" - - . = "{[list2text(., ",")]}" - -json_writer/proc/write_flat_array(list/L) - . = "\[[list2text(L, ",")]]" - -json_writer/proc/write_array(list/L) - . = list() - for(var/item in L) - . += write(item) - . = "\[[list2text(., ",")]]" - -json_writer/proc/write_string(txt) - var/static/list/json_escape = list("\\" = "\\\\", "\"" = "\\\"", "\n" = "\\n") - for(var/targ in json_escape) - var/start = 1 - while(start <= lentext(txt)) - var/i = findtext(txt, targ, start) - if(!i) - break - var/lrep = length(json_escape[targ]) - txt = "[copytext(txt, 1, i)][json_escape[targ]][copytext(txt, i + length(targ))]" - start = i + lrep - - return {""[txt]""} - -json_writer/proc/listtype(list/L) - . = LIST_FLAT - for(var/key in L) - if (. == LIST_FLAT && istype(key, /list)) - . = LIST_NESTED - if (!isnum(key) && !istype(key, /list)) - . = LIST_OBJECT - break // If it's an object, we can just stop now. - - -#undef LIST_FLAT -#undef LIST_NESTED -#undef LIST_OBJECT diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index aa47b177b88..0b336378dd4 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -18,12 +18,12 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction) spawn(1) src.canmove = 1 -/obj/effect/dummy/slaughter/ex_act(blah) +/obj/effect/dummy/slaughter/ex_act() return -/obj/effect/dummy/slaughter/bullet_act(blah) +/obj/effect/dummy/slaughter/bullet_act() return -/obj/effect/dummy/slaughter/singularity_act(blah) +/obj/effect/dummy/slaughter/singularity_act() return /obj/effect/dummy/slaughter/Destroy() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 38704ddd7d6..f084ba906f1 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -684,9 +684,6 @@ var/see_temp = H.see_invisible H.see_invisible = invis_sight - if(H.seer) - H.see_invisible = SEE_INVISIBLE_OBSERVER - if(H.glasses) if(istype(H.glasses, /obj/item/clothing/glasses)) var/obj/item/clothing/glasses/G = H.glasses diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm index 69732a8e1a4..eaa0600e83b 100644 --- a/code/modules/mob/living/carbon/human/species_types.dm +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -82,9 +82,12 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H) return 1 /datum/species/lizard/handle_speech(message) - // jesus christ why + if(copytext(message, 1, 2) != "*") - message = replacetext(message, "s", "sss") + message = regEx_replaceall(message, "(? and tags. - var/script_html = "" - for (var/script in scripts) - script_html += "" - var/stylesheet_html = "" - for (var/stylesheet in stylesheets) - stylesheet_html += "" + var/script_html = {" + + + + "} + var/stylesheet_html = {" + + + + + "} - // Generate template JSON. - var/template_data_json = "{}" - if (templates.len > 0) - template_data_json = list2json(templates) - - // Generate data JSON. + // Generate JSON. var/list/send_data = get_send_data(initial_data) - var/initial_data_json = replacetext(replacetext(list2json_usecache(send_data), """, "&#34;"), "'", "'") - - // Generate URL parameters JSON. - var/url_parameters_json = list2json(list("src" = "\ref[src]")) + var/initial_data_json = replacetext(JSON.stringify(send_data), "'", "\\'") + // Generate the HTML document. return {" - + - [script_html] [stylesheet_html] + [script_html] - -
-