conFLICTS

This commit is contained in:
MMMiracles
2015-12-16 06:26:54 -05:00
218 changed files with 5145 additions and 34266 deletions
+41 -33
View File
@@ -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
@@ -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()
..()
@@ -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()
..()
@@ -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()
..()
@@ -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))
@@ -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
@@ -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
@@ -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))
+7 -7
View File
@@ -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
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
+1 -1
View File
@@ -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)
+27 -27
View File
@@ -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)
+6 -63
View File
@@ -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 = "<i><b>[text]</b></i>: "
if (src in ticker.mode.cult)
text += "loyal|<a href='?src=\ref[src];cult=clear'>employee</a>|<b>CULTIST</b>"
text += "<br>Give <a href='?src=\ref[src];cult=tome'>tome</a>|<a href='?src=\ref[src];cult=amulet'>amulet</a>."
/*
if (objectives.len==0)
text += "<br>Objectives are empty! Set to sacrifice and <a href='?src=\ref[src];cult=escape'>escape</a> or <a href='?src=\ref[src];cult=summon'>summon</a>."
*/
text += "<br><a href='?src=\ref[src];cult=equip'>Equip</a>"
else if(isloyal(current))
text += "<b>LOYAL</b>|employee|<a href='?src=\ref[src];cult=cultist'>cultist</a>"
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 << "<span class='danger'>Spawning tome failed!</span>"
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 << "<span class='danger'>Spawning amulet failed!</span>"
usr << "<span class='danger'>equip_cultist() failed! [current]'s starting equipment will be incomplete.</span>"
else if (href_list["wizard"])
switch(href_list["wizard"])
@@ -1430,34 +1399,8 @@
special_role = "Cultist"
current << "<font color=\"purple\"><b><i>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.</b></i></font>"
current << "<font color=\"purple\"><b><i>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.</b></i></font>"
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 << "<B>Objective #1</B>: [explanation]"
current.memory += "<B>Objective #1</B>: [explanation]<BR>"
current << "The convert rune is join blood self"
current.memory += "The convert rune is join blood self<BR>"
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)
+1 -1
View File
@@ -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()]\] <span class='danger'>[user.real_name] ([user.ckey]) cast the spell [name].</span>")
spawn(0)
if(charge_type == "recharge" && recharge)
+7
View File
@@ -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
+3 -18
View File
@@ -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)
+9 -9
View File
@@ -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
+4 -3
View File
@@ -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
+8 -4
View File
@@ -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
+1 -1
View File
@@ -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)
+4 -7
View File
@@ -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
+3 -2
View File
@@ -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 = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([blob_reagent_datum.name])</span> <span class='message'>[message_a]</span></span></i></font>"
var/rendered = "<font color=\"#EE4000\">Blob Telepathy, <b>[name](<font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</font>)</b> [message_a]</font>"
for (var/mob/M in mob_list)
if(isovermind(M) || isobserver(M))
+10 -11
View File
@@ -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 << "<span class='notice'>Gained [B.point_return] resources from removing the [B].</span>"
src << "<span class='notice'>Gained [B.point_return] resources from removing \the [B].</span>"
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, <B>[speak_text]</B>"
for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs)
if(blob_minion.stat == CONSCIOUS)
src << "You broadcast with your minions, <B>[speak_text]</B>"
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: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
src << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.description]"
@@ -237,9 +236,9 @@
set category = "Blob"
set name = "*Blob Help*"
set desc = "Help on how to blob."
src << "<b>As the overmind, you can control the blob!</b>"
src << "Your blob reagent is: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!"
src << "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.description]"
src << "<b>As the overmind, you can control the blob!</b>"
src << "<b>You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.</b>"
src << "<i>Normal Blobs</i> will expand your reach and can be upgraded into special blobs that perform certain functions."
src << "<b>You can upgrade normal blobs into the following types of blob:</b>"
+71 -79
View File
@@ -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"
+36 -164
View File
@@ -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 << "<span class='cultitalic'><b>[(ishuman(user) ? "Acolyte" : "Construct")] [user]:</b> [message]</span>"
else //Emergency comms
M << "<span class='purple'><i>Acolyte ???:</i> <b>[message]</b></span>"
M << "<span class='cultitalic'><b>[(ishuman(user) ? "Acolyte" : "Construct")] [user]:</b> [message]</span>"
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 << "<B>The current game mode is - Cult!</B>"
world << "<B>Some crewmembers are attempting to start a cult!<BR>\nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult.<BR>\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.</B>"
world << "<B>Some crewmembers are attempting to start a cult!<BR>\nCultists - summon the elder god. Sacrifice crewmembers and turn them into constructs. Remember - there is no you, there is only the cult.<BR>\nPersonnel - Do not let the cult succeed in its mission. Deal with the cultists and any constructs that they might summon.</B>"
/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 << "<B>Objective #[obj_count]</B>: [explanation]"
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
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.</span>"
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 << "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>"
return 0
else
mob << "<span class='danger'>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.</span>"
mob << "<span class='danger'>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()]\] <span class='danger'>Has been converted to the cult!</span>"
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()]\] <span class='danger'>Has been converted to the cult!</span>"
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 << "<span class='greentext'>The cult wins! It has succeeded in serving its dark master!</span>"
else
feedback_set_details("round_end_result","loss - staff stopped the cult")
feedback_set("round_end_result",acolytes_survived)
world << "<span class='redtext'>The staff managed to stop the cult!</span>"
var/text = ""
if(cult_objectives.len)
text += "<br><b>The cultists' objectives were:</b>"
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) <span class='greenannounce'>Success!</span>"
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) <span class='boldannounce'>Fail.</span>"
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]. <span class='greenannounce'>Success!</span>"
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]. <span class='boldannounce'>Fail.</span>"
feedback_add_details("cult_objective","cult_sacrifice|FAIL")
else
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. <span class='boldannounce'>Fail (Gibbed).</span>"
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
else
explanation = "Summon Nar-Sie. <span class='boldannounce'>Fail.</span>"
feedback_add_details("cult_objective","cult_narsie|FAIL")
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
world << text
..()
return 1
+65
View File
@@ -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 << "<span class='warning'>An overwhelming sense of nausea overpowers you!</span>"
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. <span class='cult'>You could swear that it just moved on its own.</span>"
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 << "<span class='cultlarge'>You shouldn't waste that.</span>"
return ..()
target << "<span class='cult'>You feel the Geometer's essence violating your insides.</span>"
target << "<span class='cult'>It feels... </span><span class='cultitalic'>good.</span>"
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 << "<span class='notice'>You attempt to call out to the Geometer, but there is no answer...</span>"
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 << "<span class='notice'>You attempt to call out to the Geometer for Her shell, but you fail...</span>"
return
var/datum/game_mode/cult/cult = ticker.mode
if(cult.large_shell_summoned)
user << "<span class='cult'>Another Acolyte has already summoned Her shell. You must go forth and contact them.</span>"
return
if(cult.attempts_left <= 0)
user << "<span class='cultlarge'>The Geometer is no longer interested in you.</span>"
new /obj/structure/constructshell/large(get_turf(src))
cult.large_shell_summoned = 1
+145 -1
View File
@@ -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 << "<span class='cult'>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.</span>"
/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("<span class='cult'>\The [src] glows.</span>")
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("<span class='danger'>[user] has hit \the [src] with [O].</span>")
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("<span class='danger'>[src] was hit by [P].</span>")
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("<span class='danger'>[user] smashes against [src] with its claws.</span>",\
"<span class='danger'>You smash against [src] with your claws.</span>")
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("<span class='danger'>[M.name] has hit [src].</span>")
damaged(M.force)
/obj/structure/constructshell/large/attack_hulk(mob/user)
playsound(src, 'sound/effects/bang.ogg', 50, 1)
user.visible_message("<span class='danger'>[user] smashes [src].</span>",\
"<span class='danger'>You punch [src].</span>")
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("<span class='warning'>\The [src] glows brightly once, then falls dark. It looks strangely dull and lifeless...</span>")
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 << "<span class='cultitalic'><b>Rip... <span class='big'>Rrrip...</span> <span class='reallybig'>RRRRRRRRRR--</span></b></span>"
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"
+28 -88
View File
@@ -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("<span class='warning'>[usr] starts clawing at \his arms with \his fingernails!</span>", "<span class='cultitalic'>You begin slicing open your arms with your fingernails!</span>")
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("<span class='warning'>[usr] paints strange symbols with their own blood.</span>", "<span class='cultitalic'>You paint a messy rune with your own blood.</span>")
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 += "<center><font color='red' size=3><b><i>Archives of the Dark One</i></b></font></center><br><br><br>"
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 <b>runes</b>. 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.<br><br>A rune's name and effects can be \
revealed by examining the rune.<br><br><br>"/*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.<br><br>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.<br><br>\
<b>The Words of Power</b><br>\
\"ire\" is Travel<br>\
\"ego\" is Self<br>\
\"nahlizet\" is Blood<br>\
\"certum\" is Join<br>\
\"veri\" is Hell<br>\
\"jatkaa\" is Other<br>\
\"mgar\" is Destroy<br>\
\"balaq\" is Technology<br>\
\"karazet\" is See<br>\
\"geeri\" is Hide<br><br>\
<b>A few basic runes</b><br>\
<i>Rite of Translocation:</i> \"ire ego\"<br>\
<i>Rite of Enlightenment:</i> \"certum nahlizet ego\"<br>\
<i>Rite of Tribute:</i> \"veri nahlizet certum\"<br>\
<i>Rite of Knowledge:</i> \"karazet nahlizet ego\"<br>\
<br><br><br>"*/
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.<br><br>A rune's name and effects can be revealed by examining the rune. <br><br><br>"
text += "<font color='red'><b>Teleport</b></font><br>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 += "<font color='red'><b>Teleport Other</b></font><br>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.<br><br>"
text += "<font color='red'><b>Summon Tome</b></font><br>The Rite of Knowledge is a simplistic rune. When invoked, it will summon a single arcane tome to the rune's location before vanishing. \
<br><br>"
text += "<font color='red'><b>Convert</b></font><br>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.<br><br>"
text += "<font color='red'><b>Sacrifice</b></font><br>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.<br><br>"
@@ -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.<br><br>"
text += "<font color='red'><b>Veil Runes</b></font><br>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.<br><br>"
text += "<font color='red'><b>Reveal Runes</b></font><br>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.<br><br>"
text += "<font color='red'><b>Disguise Runes</b></font><br>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.<br><br>"
(such as the Rite of Translocation) but will be unusuable directly. Use the same rite once more to reveal these runes once more.<br><br>"
text += "<font color='red'><b>Electromagnetic Disruption</b></font><br>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.<br><br>"
@@ -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.<br><br>"
text += "<font color='red'><b>Deafen</b></font><br>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.<br><br>"
text += "<font color='red'><b>Debilitate</b></font><br>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.<br><br>"
text += "<font color='red'><b>Blind</b></font><br>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.<br><br>"
text += "<font color='red'><b>Stun</b></font><br>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.<br><br>"
text += "<font color='red'><b>Stun</b></font><br>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.<br><br>"
text += "<font color='red'><b>Summon Cultist</b></font><br>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.<br><br>"
@@ -204,15 +147,18 @@ It also contains rune words, which are soon to be removed.
text += "<font color='red'><b>Blood Boil</b></font><br>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<br><br>"
text += "<font color='red'><b>Immolate</b></font><br>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.<br><br>"
text += "<font color='red'><b>Time Stop</b></font><br>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.<br><br>"
text += "<font color='red'><b>Manifest Spirit</b></font><br>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.<br><br>"
text += "<font color='red'><b><i>Call Forth The Geometer</i></b></font><br>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.<br><br><br>"
text += "While runes are excellent for many tasks, they lack portability. The advent of <b>talismans</b> 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.<br><br><br>"
@@ -220,17 +166,11 @@ It also contains rune words, which are soon to be removed.
text += "<font color='red'><b>Talisman of Teleportation</b></font><br>The talisman form of the Rite of Translocation will transport the invoker to a randomly chosen rune of the same keyword, then \
disappear.<br><br>"
text += "<font color='red'><b>Talisman of Tome Summoning</b></font><br>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.<br><br>"
text += "<font color='red'><b>Talismans of Veiling, Revealing, and Disguising</b></font><br>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.<br><br>"
text += "<font color='red'><b>Talismans of Veiling</b></font><br>This talisman functions identically to its rune counterpart.It will disappear after one use.<br><br>"
text += "<font color='red'><b>Talisman of Electromagnetic Pulse</b></font><br>This talisman functions like the Rite of Disruption. It disappears after one use.<br><br>"
text += "<font color='red'><b>Talisman of Stunning</b></font><br>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 += "<font color='red'><b>Talisman of Immolation</b></font><br>This talisman functions exactly like the Rite of Cleansing Flame. It can only be used once.<br><br>"
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
+108 -253
View File
@@ -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 << "<b>Name:</b> [cultist_name]"
user << "<b>Effects:</b> [cultist_desc]"
//user << "<b>Words:</b> [grammar]"
user << "<b>Required Acolytes:</b> [req_cultists]"
if(req_keyword && keyword)
user << "<b>Keyword:</b> [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()
"<span class='cult'>Your vision blurs, and you suddenly appear somewhere else.</span>")
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("<span class='warning'>A frayed tome materializes on the surface of [src], which dissolves into nothing.</span>")
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 << "<span class='warning'>Something is shielding [new_cultist]'s mind!</span>"
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 << "<span class='cultlarge'>\"I desire this one for myself. <i>SACRIFICE THEM!</i>\"</span>"
return
new_cultist.visible_message("<span class='warning'>[new_cultist] writhes in pain as the markings below them glow a bloody red!</span>", \
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
ticker.mode.add_cultist(new_cultist.mind)
new_cultist.mind.special_role = "Cultist"
new_cultist << "<span class='cultitalic'><b>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.</b></span>"
new_cultist << "<span class='cultitalic'><b>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.\
</b></span>"
//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 << "<span class='cultitalic'>[offering] is too greatly linked to the world! You need more acolytes!</span>"
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 << "<span class='cultlarge'>\"Even I have standards, such as they are!\"</span>"
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 << "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>"
if(ishuman(T) || isrobot(T))
M << "<span class='cultlarge'>\"I accept this sacrifice.\"</span>"
else
if(ishuman(T) || isrobot(T))
M << "<span class='cultlarge'>\"I accept this sacrifice.\"</span>"
else
M << "<span class='cultlarge'>\"I accept this meager sacrifice.\"</span>"
M << "<span class='cultlarge'>\"I accept this meager sacrifice.\"</span>"
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 << "<span class='cultlarge'><i>\"YOUR SOUL BURNS WITH YOUR ARROGANCE!!!\"</i></span>"
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 << "<span class='warning'>The sacrifice is not complete. The portal lacks the power to open!</span>"
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 << "<span class='warning'>The avatar of Nar-Sie is already on this plane!</span>"
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 << "<span class='cultitalic'><b>Rip... <span class='big'>Rrrip...</span> <span class='reallybig'>RRRRRRRRRR--</span></b></span>"
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("<span class='warning'><b>[mob_to_sacrifice]'s body rises into the air, connected to [mob_to_revive] by a glowing tendril!</span>")
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("<span class='warning'><b>[mob_to_sacrifice] disintegrates into a pile of bones[mob_to_revive ? ", the glowing tendril sinking into [mob_to_revive]'s body":""].</span>")
if(!mob_to_sacrifice || !in_range(mob_to_sacrifice, src))
return
mob_to_sacrifice.visible_message("<span class='warning'><b>[mob_to_sacrifice] disintegrates into a pile of bones[mob_to_revive ? ", the glowing tendril sinking into [mob_to_revive]'s body":""].</span>")
mob_to_sacrifice.dust()
if(!mob_to_revive || mob_to_revive.stat != DEAD)
visible_message("<span class='warning'>The glowing tendril snaps against the rune with a shocking crack.</span>")
@@ -561,63 +416,27 @@ var/list/teleport_other_runes = list()
M.visible_message("<span class='warning'>[M] twitches.</span>")
//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("<span class='warning'>[src] darkens to black and vanishes.</span>")
for(var/obj/effect/rune/R in orange(3,src))
R.visible_message("<span class='danger'>[R] fades away.</span>")
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 << "<span class='cultitalic'>You suddenly feel as if you've vanished...</span>"
O.invisibility = INVISIBILITY_OBSERVER
if(R.invisibility == INVISIBILITY_OBSERVER)
R.invisibility = 0
R.alpha = initial(R.alpha)
else
R.visible_message("<span class='danger'>[R] fades away.</span>")
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("<span class='warning'>[src] explodes in a flash of blinding light!</span>")
for(var/mob/dead/observer/O in orange(3,src))
O << "<span class='cultitalic'>You suddenly feel very obvious...</span>"
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("<span class='warning'>[src] flares brightly, then slowly dulls and appears mundane.</span>")
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("<span class='warning'>[src] glows blue for a moment before vanishing.</span>")
@@ -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("<span class='warning'>[src] blurs for a moment before fading away.</span>")
for(var/mob/living/carbon/C in range(7,src))
if(!iscultist(C) && !C.null_rod_check())
C << "<span class='warning'>The world around you goes quiet.</span>"
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("<span class='warning'>[src] emits a blinding red flash!</span>")
for(var/mob/living/carbon/C in viewers(src))
if(!iscultist(C) && !C.null_rod_check())
C << "<span class='cultitalic'><b>You can't see!</b></span>"
C << "<span class='cultlarge'>You feel oily shadows cover your senses.</span>"
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("<span class='warning'>[src] explodes in a bright flash!</span>")
for(var/mob/living/M in viewers(src))
if(!iscultist(M) && !M.null_rod_check())
M << "<span class='cultitalic'><b>You are disoriented by [src]!</b></span>"
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 << "<span class='cultitalic'><b>You are disoriented by [src]!</b></span>"
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("<span class='warning'>[cultist_to_summon] suddenly disappears in a flash of red light!</span>", \
"<span class='cultitalic'><b>Overwhelming vertigo consumes you as you are hurled through the air!</b></span>")
visible_message("<span class='warning'>A foggy shape materializes atop [src] and solidifes into [cultist_to_summon]!</span>")
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("<span class='warning'>With the sound of clanging metal, [src] crumbles to dust!</span>")
@@ -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("<span class='warning'>[src] briefly bubbles before exploding!</span>")
@@ -973,7 +771,7 @@ var/list/teleport_other_runes = list()
continue
C << "<span class='cultlarge'>Your blood boils in your veins!</span>"
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 << "<span class='cultitalic'>[src] saps your strength!</span>"
@@ -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("<span class='warning'>[src] burns away, scorching the floor below!</span>")
for(var/mob/living/carbon/C in viewers(src))
if(!iscultist(C) && !C.null_rod_check())
C << "<span class='cultlarge'>You feel your skin crisp as you burst into flames!</span>"
C.fire_act()
user.apply_damage(15, BURN, pick("l_arm", "r_arm"))
user << "<span class='cultitalic'>[src] burns your arms!</span>"
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("<span class='warning'>[src] flares up for a moment, and then disappears into itself!</span>")
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 << "<span class='cultitalic'>[src] temporarily stops your heart from beating!</span>"
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
..()
+58 -131
View File
@@ -26,8 +26,8 @@ Rite of Disorientation
user << "<b>Name:</b> [cultist_name]"
user << "<b>Effect:</b> [cultist_desc]"
user << "<b>Uses Remaining:</b> [uses]"
return
..()
else
user << "<span class='danger'>There are indecipherable images scrawled on the paper in what looks to be... <i>blood?</i></span>"
/obj/item/weapon/paper/talisman/attack_self(mob/living/user)
if(!iscultist(user))
@@ -70,12 +70,11 @@ Rite of Disorientation
var/dat = "<B>There are [uses] bloody runes on the parchment.</B><BR>"
dat += "Please choose the chant to be imbued into the fabric of reality.<BR>"
dat += "<HR>"
dat += "<A href='?src=\ref[src];rune=newtome'>N'ath reth sh'yro eth d'raggathnor!</A> - Allows you to summon an arcane tome.<BR>"
dat += "<A href='?src=\ref[src];rune=teleport'>Sas'so c'arta forbici!</A> - Allows you to move to a Rite of Dislocation with the keyword of \"veri\".<BR>"
dat += "<A href='?src=\ref[src];rune=emp'>Ta'gh fara'qha fel d'amar det!</A> - Allows you to destroy technology in a short range.<BR>"
dat += "<A href='?src=\ref[src];rune=conceal'>Kla'atu barada nikt'o!</A> - Allows you to conceal nearby runes.<BR>"
dat += "<A href='?src=\ref[src];rune=reveal'>Nikt'o barada kla'atu!</A> - Allows you to reveal nearby runes.<BR>"
dat += "<A href='?src=\ref[src];rune=runestun'>Fuu ma'jin!</A> - Allows you to stun a person by attacking them with the talisman.<BR>"
dat += "<A href='?src=\ref[src];rune=conceal'>Kla'atu barada nikt'o!</A> - Allows you to conceal nearby runes, or reveal previously concealed runes.<BR>"
dat += "<A href='?src=\ref[src];rune=flame'>Dedo va'batoh!</A> - Allows you to set nearby non-believers on fire.<BR>"
dat += "<A href='?src=\ref[src];rune=sacrune'>Barhah hra zar'garis!</A> - A sacrifice rune appears under your feet, ready to be invoked in the name of Nar-sie.<BR>"
dat += "<A href='?src=\ref[src];rune=soulstone'>Kal'om neth!</A> - Summons a soul stone, used to capure the spirits of dead or dying humans.<BR>"
dat += "<A href='?src=\ref[src];rune=construct'>Daa'ig osk!</A> - Summons a construct shell for use with captured souls. It is too large to carry on your person.<BR>"
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("<span class='warning'>[src] crumbles to dust.</span>")
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("<span class='warning'>[src] crumbles to dust.</span>")
qdel(src)
//Rite of Translocation: Same as rune
/obj/item/weapon/paper/talisman/teleport
@@ -162,65 +152,24 @@ Rite of Disorientation
user << "<b>Keyword:</b> [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("<span class='warning'>[user]'s hand glows red for a moment.</span>", \
"<span class='cultitalic'>You speak the words of the talisman!</span>")
var/obj/item/weapon/tome/T = new(get_turf(user))
if(user.put_in_hands(T))
user.visible_message("<span class='warning'>A tome appears in [user]'s hand!</span>", \
"<span class='cultitalic'>An arcane tome materializes in your free hand.</span>")
else
user.visible_message("<span class='warning'>A tome appears at [user]'s feet!</span>", \
"<span class='cultitalic'>An arcane tome materialzies at your feet.</span>")
//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("<span class='warning'>Dust flows from [user]'s hand.</span>", \
"<span class='cultitalic'>You speak the words of the talisman, veiling nearby runes.</span>")
for(var/obj/effect/rune/R in orange(3,user))
R.visible_message("<span class='danger'>[R] fades away.</span>")
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("<span class='warning'>A flash of light shines from [user]'s hand!</span>", \
"<span class='cultitalic'>You speak the words of the talisman, revealing nearby runes.</span>")
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("<span class='warning'>Dust flows from [user]s hand.</span>", \
"<span class='cultitalic'>You speak the words of the talisman, making nearby runes appear fake.</span>")
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("<span class='danger'>[R] fades away.</span>")
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 << "<span class='warning'>To use this talisman, attack the target directly.</span>"
else
user << "<span class='danger'>There are indecipherable images scrawled on the paper in what looks to be... <i>blood?</i></span>"
/obj/item/weapon/paper/talisman/stun/attack(mob/living/target, mob/living/user)
if(iscultist(user))
user.whisper(invocation)
user.visible_message("<span class='warning'>[user] holds up [src], which explodes in a flash of red light!</span>", \
"<span class='cultitalic'>You stun [target] with the talisman!</span>")
var/obj/item/weapon/nullrod/N = locate() in target
if(N)
target.visible_message("<span class='warning'>[target]'s null rod absorbs the talisman's light!</span>", \
"<span class='userdanger'>Your null rod absorbs the blinding light!</span>")
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("<span class='warning'>\The [src] in [user]'s hand suddenly burns away in a red flash!</span>", \
"<span class='cultitalic'>You speak the words of the talisman, setting your enemies on fire.</span>")
for(var/mob/living/carbon/C in viewers(user))
if(!iscultist(C) && !C.null_rod_check())
C << "<span class='cultlarge'>You feel your skin crisp as you burst into flames!</span>"
C.fire_act()
//Rite of Arming: Equips cultist armor on the user, where available
+5
View File
@@ -113,6 +113,10 @@
synd_mind.current.real_name = "[syndicate_name()] [leader_title]"
synd_mind.current << "<B>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.</B>"
synd_mind.current << "<B>If you feel you are not up to this task, give your ID to another operative.</B>"
synd_mind.current << "<B>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.</B>"
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
@@ -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
+1 -1
View File
@@ -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
+6 -9
View File
@@ -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 << "<span class='danger'>The Geometer of blood wants this mortal sacrificed with the rune.</span>"
else
user << "<span class='danger'>The soul stone doesn't work for no apparent reason.</span>"
return 0
if(imprinted != "empty")
user << "<span class='userdanger'>Capture failed!</span>: The soul stone has already been imprinted with [imprinted]'s mind!"
else
@@ -200,7 +197,7 @@
if(stoner && iswizard(stoner))
newstruct << "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>"
else if(stoner && iscultist(stoner))
newstruct << "<B>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</B>"
newstruct << "<B>You are still bound to serve the cult, follow their orders and help them summon the Geometer at all costs.</B>"
else newstruct << "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>"
newstruct.cancel_camera()
+96 -99
View File
@@ -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" = "O<sub>2</sub>",
"carbon dioxide" = "CO<sub>2</sub>",
"plasma" = "Toxin",
"other" = "Other")
"oxygen" = "O<sub>2</sub>",
"nitrogen" = "N<sub>2</sub>",
"carbon dioxide" = "CO<sub>2</sub>",
"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)
+61 -62
View File
@@ -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 <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding]<br>"
else
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the <span class='boldannounce'>air</span><br>"
else
if (holding)
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the [holding]<br>"
else
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the <span class='boldannounce'>air</span><br>"
if(air_contents.toxins > 0)
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains plasma! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
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)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains N2O! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
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 <span class='boldannounce'>air</span><br>", "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 <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding]<br>"
else
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the <span class='boldannounce'>air</span><br>"
else
if (holding)
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the [holding]<br>"
else
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the <span class='boldannounce'>air</span><br>"
if(air_contents.toxins > 0)
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains plasma! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
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)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) opened a canister that contains N2O! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
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 <span class='boldannounce'>air</span><br>", "atmos")
holding.loc = loc
holding = null
add_fingerprint(usr)
update_icon()
return 1
/obj/machinery/portable_atmospherics/canister/toxins/New()
..()
+2
View File
@@ -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 << "<b>[U]</b> holds <a href='?_src_=usr;show_paper=1;'>\a [itemname]</a> up to one of your cameras ..."
else
@@ -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 << "<span class='warning'>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.</span>"
return 0
..()
#undef SYNDICATE_CHALLENGE_TIMER
@@ -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
@@ -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
+7
View File
@@ -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
+45 -53
View File
@@ -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].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
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].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
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 << "<span class='warning'>You need an empty hand to remove \the [cell]!</span>"
return
cell.updateicon()
usr.put_in_hands(cell)
cell.add_fingerprint(usr)
usr.visible_message("\The [usr] removes \the [cell] from \the [src].", "<span class='notice'>You remove \the [cell] from \the [src].</span>")
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 << "<span class='warning'>You need an empty hand to remove \the [cell]!</span>"
return
cell = C
C.loc = src
C.add_fingerprint(usr)
usr.visible_message("\The [usr] inserts \a [C] into \the [src].", "<span class='notice'>You insert \the [C] into \the [src].</span>")
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].", "<span class='notice'>You remove \the [cell] from \the [src].</span>")
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].", "<span class='notice'>You insert \the [C] into \the [src].</span>")
add_fingerprint(usr)
return 1
/obj/machinery/space_heater/process()
if(!on || (stat & BROKEN))
@@ -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 = "<font color = #666633>-% New frequency filter assigned: \"[newfreq] GHz\" %-</font color>"
if(newfreq == SYND_FREQ)
temp = "<font color = #FF0000>-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-</font color>"
else
if(!(newfreq in freq_listening) && newfreq < 10000)
freq_listening.Add(newfreq)
temp = "<font color = #666633>-% New frequency filter assigned: \"[newfreq] GHz\" %-</font color>"
if(href_list["delete"])
@@ -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
+2
View File
@@ -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)
@@ -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
+9 -1
View File
@@ -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 << "<span class='notice'>The [src] says \"[toysay]\"</span>"
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"
@@ -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)
@@ -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 << "<span class='warning'>You can't heal yourself!</span>"
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))
+32 -31
View File
@@ -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 << "<span class='notice'>You close the tank release valve.</span>"
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 << "<span class='notice'>You open \the [src] valve.</span>"
usr << "<span class='notice'>You close the tank release valve.</span>"
if (location.internals)
location.internals.icon_state = "internal1"
location.internals.icon_state = "internal0"
else
usr << "<span class='warning'>You need something to connect to \the [src]!</span>"
if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS))
location.internal = src
usr << "<span class='notice'>You open \the [src] valve.</span>"
if (location.internals)
location.internals.icon_state = "internal1"
else
usr << "<span class='warning'>You need something to connect to \the [src]!</span>"
return 1
/obj/item/weapon/tank/remove_air(amount)
return air_contents.remove(amount)
+1 -1
View File
@@ -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)
@@ -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'
+3 -2
View File
@@ -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
+1 -2
View File
@@ -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)
-106
View File
@@ -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()
-1
View File
@@ -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!
+1 -2
View File
@@ -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<numCultists, i++)
H = pick(candidates)
+4 -4
View File
@@ -8,7 +8,7 @@
name = "Unknown"
var/mobname = "default" //Use for the ghost spawner variant, so they don't come out named "sleeper"
var/mobgender = MALE //Set to male by default due to the patriarchy. Other options include FEMALE and NEUTER
var/mob_species = null //Set to make them a mutant race such as lizard or skeleton
var/mob_species = null //Set to make them a mutant race such as lizard or skeleton. Uses the datum typepath instead of the ID.
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
var/corpsesuit = null
var/corpseshoes = null
@@ -262,7 +262,7 @@
/obj/effect/landmark/corpse/plasmaman
mob_species = "plasmaman"
mob_species = /datum/species/plasmaman
corpsehelmet = /obj/item/clothing/head/helmet/space/plasmaman
corpseuniform = /obj/item/clothing/under/plasmaman
corpseback = /obj/item/weapon/tank/internals/plasmaman/full
@@ -320,7 +320,7 @@
/obj/effect/landmark/corpse/skeleton
name = "skeletal remains"
mobname = "skeleton"
mob_species = "skeleton"
mob_species = /datum/species/skeleton
mobgender = NEUTER
@@ -335,7 +335,7 @@
/obj/effect/landmark/corpse/zombie
name = "rotting corpse"
mobname = "zombie"
mob_species = "zombie"
mob_species = /datum/species/zombie
/obj/effect/landmark/corpse/zombie/alive
death = FALSE
+240 -262
View File
@@ -1,262 +1,240 @@
/*
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({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "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({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "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({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "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({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "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()
+8
View File
@@ -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"])
+5
View File
@@ -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 += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
dat += "<b>UI Style:</b> <a href='?_src_=prefs;preference=ui'>[UI_style]</a><br>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(nanoui_fancy) ? "Yes" : "No"]</a><br>"
dat += "<b>Play admin midis:</b> <a href='?_src_=prefs;preference=hear_midis'>[(toggles & SOUND_MIDI) ? "Yes" : "No"]</a><br>"
dat += "<b>Play lobby music:</b> <a href='?_src_=prefs;preference=lobby_music'>[(toggles & SOUND_LOBBY) ? "Yes" : "No"]</a><br>"
dat += "<b>Ghost ears:</b> <a href='?_src_=prefs;preference=ghost_ears'>[(chat_toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]</a><br>"
@@ -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")
@@ -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
+2 -1
View File
@@ -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)
..()
+8 -8
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 610 B

@@ -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 + "<link rel=\"stylesheet\" type=\"text/css\" href=\"nanotrasen.css\" />"
src.head = src.head + "<link rel=\"stylesheet\" type=\"text/css\" href=\"hi-nanotrasen.css\" />"
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)
+282 -10
View File
@@ -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)
// ************************************ 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
-187
View File
@@ -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].")
-9
View File
@@ -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
-67
View File
@@ -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
+3 -3
View File
@@ -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()
@@ -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
@@ -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, "(?<!s)s(?!s)", "sss") //(?<!s) Not s before. (?!s) not s after. That way it only triples a single s instead of double ss.
message = regEx_replaceall(message, "(?<!s)ss(?!s)", "ssss")
message = regEx_replaceall(message, "(?<!S)S(?!S)", "SSS")
message = regEx_replaceall(message, "(?<!S)SS(?!S)", "SSSS")
return message
@@ -163,6 +166,7 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
name = "???"
id = "shadow"
darksight = 8
invis_sight = SEE_INVISIBLE_MINIMUM
sexes = 0
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
@@ -216,3 +216,7 @@
else
target.see_invisible = SEE_INVISIBLE_LIVING
name = "Toggle Nightvision \[OFF]"
/mob/living/simple_animal/hostile/statue/sentience_act()
faction -= "neutral"
@@ -24,7 +24,7 @@
see_in_dark = 8
languages = ALL
response_help = "passes through"
response_disarm = "swings at"
response_disarm = "swings through"
response_harm = "punches through"
unsuitable_atmos_damage = 0
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) //I don't know how you'd apply those, but revenants no-sell them anyway.
@@ -89,10 +89,9 @@
charge_max = 200
range = 5
stun = 30
reveal = 100
cast_amount = 40
var/shock_range = 2
var/shock_damage = 18
var/shock_damage = 20
action_icon_state = "overload_lights"
/obj/effect/proc_holder/spell/aoe_turf/revenant/overload/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
@@ -217,7 +216,7 @@
desc = "Causes nearby living things to waste away."
charge_max = 200
range = 3
reveal = 60
reveal = 50
cast_amount = 50
unlock_amount = 200
action_icon_state = "blight"
@@ -37,7 +37,7 @@
stagedamage++
affected_mob.adjustToxLoss(stage*3) //should, normally, do about 45 toxin damage.
PoolOrNew(/obj/effect/overlay/temp/revenant, affected_mob.loc)
if(prob(45))
if(!finalstage && prob(45))
affected_mob.adjustStaminaLoss(stage*2)
..() //So we don't increase a stage before applying the stage damage.
switch(stage)
@@ -513,3 +513,7 @@
nest.spawned_mobs -= src
nest = null
return ..()
/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
return
-1
View File
@@ -87,7 +87,6 @@
var/obj/item/r_hand = null//Living
var/obj/item/weapon/storage/s_active = null//Carbon
var/seer = 0 //for cult//Carbon, probably Human
var/see_override = 0 //0 for no override, sets see_invisible = see_override in mob life process
var/datum/hud/hud_used = null
+16 -3
View File
@@ -27,6 +27,20 @@
datum/topic_state/state = default_state)
return -1 // Sorta implemented.
/**
* public
*
* Called on a NanoUI when the UI receieves a href.
* Think of this as Topic().
*
* required action string The action/button that has been invoked by the user.
* required params list A list of parameters attached to the button.
*
* return bool If the UI should be updated or not.
**/
/atom/movable/proc/ui_act(action, list/params)
return // Not implemented.
/**
* public
*
@@ -81,6 +95,5 @@
var/href = "close=1"
src.Topic(href, params2list(href), ui.ref)
// Otherwise, if we use the legacy logic, unset the mob's machine.
else if (ui.on_close_logic)
if(src && src.mob)
src.mob.unset_machine()
else if(src && src.mob)
src.mob.unset_machine()
+127 -248
View File
@@ -22,19 +22,19 @@
var/window_id // The window_id for browse() and onclose().
var/width = 0 // The window width.
var/height = 0 // The window height
var/on_close_logic = 1 // Enable legacy onclose() logic.
var/atom/ref = null // An extra ref to use when the window is closed.
var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // Extra options to winset().
var/list/stylesheets = list() // The list of CSS stylesheets to apply to the NanoUI..
var/list/scripts = list() // The list of Javascript scripts to apply to the NanoUI.
var/templates[0] // The list of NanoUI templates available to the NanoUI.
var/layout_key = "default" // The layout_key used to load alternate layouts and CSS.
var/state_key = "default" // The state of the frontend.
var/window_options = list( // Extra options to winset().
"focus" = 0,
"titlebar" = 1,
"can_resize" = 1,
"can_minimize" = 1,
"can_maximize" = 0,
"can_close" = 1,
"auto_format" = 0
)
var/atom/ref = null // An extra ref to call when the window is closed.
var/layout = "nanotrasen" // The layout to be used for this UI.
var/template // The template to be used for this UI.
var/auto_update = 1 // Update the NanoUI every MC tick.
var/auto_update_layout = 0 // Re-render the layout every update.
var/auto_update_content = 1 // Re-render the content every update.
var/show_map = 0 // Show the Map UI.
var/map_z_level = 1 // Map Z-level.
var/list/initial_data // The data (and datastructure) used to initialize the NanoUI
var/status = NANO_INTERACTIVE // The status/visibility of the NanoUI.
var/datum/topic_state/state = null // Topic state used to determine status. Topic states are in interactions/.
@@ -66,9 +66,9 @@
src.user = user
src.src_object = src_object
src.ui_key = ui_key
src.window_id = "[ui_key]\ref[src_object]"
src.window_id = "\ref[src_object]-[ui_key]"
add_template("main", template)
set_template(template)
if (title)
src.title = sanitize(title)
@@ -85,76 +85,9 @@
master_ui.children += src
src.state = state
add_common_assets()
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/nanoui)
assets.send(user)
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
assets.send(user, template)
/**
* private
*
* Add the assets required by all NanoUIs.
**/
/datum/nanoui/proc/add_common_assets()
// Libraries: jQuery, jQuery-UI, and doT.
add_script("jquery.js")
add_script("jquery-ui.js")
add_script("doT.js")
// Nano Utility: Utility functions and sanity checks.
add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions.
// Nano Template: Renders templates using doT.
add_script("nano_template.js")
// Nano State Manager: Handles server updates and passes them to the current state.
add_script("nano_state_manager.js")
// Nano State: Base state.
add_script("nano_state.js")
// Nano State/Default: State used by all NanoUIs by default.
add_script("nano_state_default.js")
// Nano Base Callbacks: Used to set up callbacks across all NanoUIs.
add_script("nano_base_callbacks.js")
// Nano Base Helpers: Template helpers common across all NanoUIs.
add_script("nano_base_helpers.js")
// CSS reset.
add_stylesheet("normalize.css")
// Common style elements.
add_stylesheet("shared.css")
// Icons.
add_stylesheet("icons.css")
/**
* private
*
* Set the status/visibility of the NanoUI.
*
* required state int The status to set (NANO_CLOSE/NANO_DISABLED/NANO_UPDATE/NANO_INTERACTIVE).
* optional push_update bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/set_status(state, push_update = 0)
if (state != status) // Only update if status has changed.
if (status == NANO_DISABLED)
status = state
if (push_update)
update()
else
status = state
if (push_update || status == 0) // Force an update if NANO_DISABLED.
push_data(null, 1)
/**
* private
*
* Update the status/visibility of the NanoUI for its user.
*
* optional push_update bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/update_status(push_update = 0)
var/new_status = src_object.CanUseTopic(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
set_status(new_status, push_update)
if(new_status == NANO_CLOSE)
close()
/**
* public
@@ -187,17 +120,25 @@
/datum/nanoui/proc/get_config_data()
var/list/config_data = list(
"title" = title,
"srcObject" = list(
"name" = src_object.name
),
"stateKey" = state_key,
"status" = status,
"autoUpdateLayout" = auto_update_layout,
"autoUpdateContent" = auto_update_content,
"showMap" = show_map,
"mapZLevel" = map_z_level,
"ref" = "\ref[src]",
"window" = list(
"width" = width,
"height" = height,
"ref" = window_id
),
"user" = list(
"name" = user.name
"name" = user.name,
"fancy" = user.client.prefs.nanoui_fancy,
"ref" = "\ref[user]"
),
"srcObject" = list(
"name" = src_object.name,
"ref" = "\ref[src_object]"
),
"templates" = list(
"layout" = "_[layout]",
"content" = "[template]"
)
)
return config_data
@@ -224,115 +165,31 @@
*
* Sets the browse() window options for this NanoUI.
*
* required window_options string The window options to set.
* required window_options list The window options to set.
**/
/datum/nanoui/proc/set_window_options(window_options)
/datum/nanoui/proc/set_window_options(list/window_options)
src.window_options = window_options
/**
* public
*
* Add a stylesheet to the NanoUI.
* This must be called before the NanoUI is opened.
* Set the layout for this NanoUI.
* This loads custom layout styles and templates for this NanoUI.
*
* required file string The path of the stylesheet file to add.
* required layout string The new UI layout.
**/
/datum/nanoui/proc/add_stylesheet(file)
stylesheets.Add(file)
/datum/nanoui/proc/set_layout(layout)
src.layout = lowertext(layout)
/**
* public
*
* Add a script to the NanoUI.
* This must be called before the NanoUI is opened.
* Set the template for this NanoUI.
*
* required file string The path of the script file to add.
* required template string The new UI template.
**/
/datum/nanoui/proc/add_script(file)
scripts.Add(file)
/**
* public
*
* Add a template to the NanoUI.
* This must be called before the NanoUI is opened.
*
* required key string The key used to reference this file in the frontend.
* required file string The path of the template file to add.
**/
/datum/nanoui/proc/add_template(key, filename)
templates[key] = filename
/**
* public
*
* Set the layout key for this NanoUI.
* This loads two files during get_html(): 'layout_[layout_key].tmpl' and 'layout_[layout_key].css'.
*
* required layout_key string The new layout key.
**/
/datum/nanoui/proc/set_layout_key(layout_key)
src.layout_key = lowertext(layout_key)
/**
* public
*
* Enable/disable auto-updating of the NanoUI layout.
*
* required state bool Enable/disable auto-updating of the layout.
**/
/datum/nanoui/proc/set_auto_update_layout(state)
auto_update_layout = state
/**
* public
*
* Enable/disable auto-updating of the NanoUI content.
*
* required state bool Enable/disable auto-updating of the content.
**/
/datum/nanoui/proc/set_auto_update_content(state)
auto_update_content = state
/**
* public
*
* Set the state key used in the frontend.
*
* required state_key string The new state key..
**/
/datum/nanoui/proc/set_state_key(state_key)
src.state_key = state_key
/**
* public
*
* Toggle showing the Map UI.
*
* required state bool Enable/disable the Map UI.
**/
/datum/nanoui/proc/set_show_map(state)
show_map = state
/**
* public
*
* Set the map Z-level.
*
* required z int The new Z-level.
**/
/datum/nanoui/proc/set_map_z_level(z)
map_z_level = z
/**
* public
*
* Enable/disable legacy on_close logic.
*
* required state bool Enable/disable the logic.
**/
/datum/nanoui/proc/use_on_close_logic(state)
on_close_logic = state
/datum/nanoui/proc/set_template(template)
src.template = lowertext(template)
/**
* private
@@ -342,56 +199,50 @@
* return string NanoUI HTML output.
**/
/datum/nanoui/proc/get_html()
// Add files based on the layout key.
add_stylesheet("layout_[layout_key].css")
add_template("layout", "layout_[layout_key].tmpl")
// Generate <script> and <link> tags.
var/script_html = ""
for (var/script in scripts)
script_html += "<script type='text/javascript' src='[script]'></script>"
var/stylesheet_html = ""
for (var/stylesheet in stylesheets)
stylesheet_html += "<link rel='stylesheet' type='text/css' href='[stylesheet]' />"
var/script_html = {"
<script type='text/javascript' src='nanoui.lib.js'></script>
<script type='text/javascript' src='nanoui.main.js'></script>
<script type='text/javascript' src='nanoui.templates.js'></script>
"}
var/stylesheet_html = {"
<link rel="stylesheet" type='text/css' href='http://css-spinners.com/css/spinner/hexdots.css'>
<link rel='stylesheet' type='text/css' href='nanoui.lib.css' />
<link rel='stylesheet' type='text/css' href='nanoui.common.css' />
<link rel='stylesheet' type='text/css' href='nanoui.[layout].css' />
"}
// 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;", "&amp;#34;"), "'", "&#39;")
// 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 {"
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<script type='text/javascript'>
function receiveUpdateData(jsonString)
{
if (typeof NanoStateManager != 'undefined' && typeof jQuery != 'undefined')
{
NanoStateManager.receiveUpdateData(jsonString);
function receiveUpdate(dataString) {
if (typeof NanoBus !== 'undefined') {
NanoBus.emit('serverUpdate', dataString);
}
}
};
</script>
[script_html]
[stylesheet_html]
[script_html]
</head>
<body scroll=auto data-template-data='[template_data_json]' data-initial-data='[initial_data_json]' data-url-parameters='[url_parameters_json]'>
<div id="uiLayout"></div>
<noscript>
<div id="uiNoScript">
<h1>Javascript Required</h1>
<hr />
<p>Javascript is required in order to use this NanoUI interface.</p>
<p>Please enable Javascript in Internet Explorer, and restart your game.</p>
<body>
<div id='data' data-initial='[initial_data_json]'></div>
<div id='layout'>
<div class='hexdots-loader' style='position:fixed;top:50%;left:50%;transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);'>
Sending Resources...
</div>
</div>
<noscript>
<h1>Javascript Required</h1>
<p>Javascript is required in order to use this NanoUI interface.</p>
<p>Please enable Javascript in Internet Explorer, and restart your game.</p>
</noscript>
</body>
</html>
@@ -415,12 +266,11 @@
var/window_size = ""
if (width && height) // If we have a width and height, use them.
window_size = "size=[width]x[height];"
update_status(push_update = 0) // Update the window state.
update_status(push = 0) // Update the window state.
if (status == NANO_CLOSE)
return // Bail if we should close.
user << browse(get_html(), "window=[window_id];[window_size][window_options]") // Open the window.
winset(user, "mapwindow.map", "focus=true") // Return keyboard focus to map.
user << browse(get_html(), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
winset(user, window_id, "on-close=\"nanoclose \ref[src]\"") // Instruct the client to signal NanoUI when the window is closed.
SSnano.ui_opened(src) // Call the opened handler.
@@ -435,7 +285,7 @@
**/
/datum/nanoui/proc/reinitialize(template, list/data)
if(template)
add_template("main", template) // Replace the 'main' template.
src.template = template // Set a new template.
if(data)
set_initial_data(data) // Replace the initial_data.
open()
@@ -458,17 +308,17 @@
* Push data to an already open NanoUI.
*
* required data list The data to send.
* optional force_push bool If the update should be sent regardless of state.
* optional force bool If the update should be sent regardless of state.
**/
/datum/nanoui/proc/push_data(data, force_push = 0)
update_status(push_update = 0) // Update the window state.
if (status == NANO_DISABLED && !force_push)
/datum/nanoui/proc/push_data(data, force = 0)
update_status(push = 0) // Update the window state.
if (status == NANO_DISABLED && !force)
return // Cannot update UI, we have no visibility.
var/list/send_data = get_send_data(data) // Get the data to send.
// Send the new data to the recieveUpdateData() Javascript function.
user << output(list2params(list(list2json_usecache(send_data))),"[window_id].browser:receiveUpdateData")
// Send the new data to the recieveUpdate() Javascript function.
user << output(list2params(list(JSON.stringify(send_data))), "[window_id].browser:receiveUpdate")
/**
* private
@@ -478,22 +328,16 @@
* If the src_object's Topic() returns 1, update all UIs attacked to it.
**/
/datum/nanoui/Topic(href, href_list)
update_status(push_update = 0) // Update the window state.
update_status(push = 0) // Update the window state.
if (status != NANO_INTERACTIVE || user != usr)
return // If UI is not interactive or usr calling Topic is not the UI user.
var/update = src_object.Topic(href, href_list, 0, state) // Call Topic() on the src_object.
var/action = href_list["nano"] // Pull the action out.
href_list -= "nano"
// Code to toggle/update the Map UI.
var/map_update = 0
if(href_list["showMap"])
set_show_map(text2num(href_list["showMap"]))
map_update = 1
if(href_list["mapZLevel"])
set_map_z_level(text2num(href_list["mapZLevel"]))
map_update = 1
var/update = src_object.ui_act(action, href_list, state) // Call Topic() on the src_object.
if ((src_object && update) || map_update)
if (src_object && update)
SSnano.update_uis(src_object) // If we have a src_object and its Topic() told us to update.
/**
@@ -502,17 +346,17 @@
* Update the NanoUI. Only updates the contents/layout if update is true,
* otherwise only updates the status.
*
* optional update bool If the UI should be updated (or just the status).
* optional force bool If the UI should be forced to update.
**/
/datum/nanoui/process(update = 0)
/datum/nanoui/process(force = 0)
if (!src_object || !user) // If the object or user died (or something else), abort.
close()
return
if (status && (update || auto_update))
if (status && (force || auto_update))
update() // Update the UI if the status and update settings allow it.
else
update_status(push_update = 1) // Otherwise only update status.
update_status(push = 1) // Otherwise only update status.
/**
* private
@@ -524,3 +368,38 @@
**/
/datum/nanoui/proc/update(force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
/**
* private
*
* Set the status/visibility of the NanoUI.
*
* required state int The status to set (NANO_CLOSE/NANO_DISABLED/NANO_UPDATE/NANO_INTERACTIVE).
* optional push bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/set_status(state, push = 0)
if (state != status) // Only update if status has changed.
if (status == NANO_DISABLED)
status = state
if (push)
update()
else
status = state
if (push || status == 0) // Force an update if NANO_DISABLED.
push_data(null, 1)
/**
* private
*
* Update the status/visibility of the NanoUI for its user.
*
* optional push bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/update_status(push = 0)
var/new_status = src_object.CanUseTopic(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
set_status(new_status, push)
if(new_status == NANO_CLOSE)
close()
+2 -2
View File
@@ -81,7 +81,7 @@
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) // Check the UI is valid.
ui.process(update = 1) // Update the UI.
ui.process(force = 1) // Update the UI.
update_count++ // Count each UI we update.
return update_count
@@ -125,7 +125,7 @@
var/update_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.process(update = 1) // Update the UI.
ui.process(force = 1) // Update the UI.
update_count++ // Count each UI we upadte.
return update_count
+2 -5
View File
@@ -54,10 +54,6 @@
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper)
assets.send(user)
if(istype(src, /obj/item/weapon/paper/talisman)) //Talismans cannot be read
if(!iscultist(user) && !user.stat)
user << "<span class='danger'>There are indecipherable images scrawled on the paper in what looks to be... <i>blood?</i></span>"
return
if(in_range(user, src) || isobserver(user))
if( !(ishuman(user) || isobserver(user) || issilicon(user)) )
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>", "window=[name]")
@@ -202,6 +198,7 @@
t = "<font face=\"[PEN_FONT]\" color=[P.colour]>[t]</font>"
else // If it is a crayon, and he still tries to use these, make them empty!
var/obj/item/toy/crayon/C = P
t = replacetext(t, "\[*\]", "")
t = replacetext(t, "\[hr\]", "")
t = replacetext(t, "\[small\]", "")
@@ -209,7 +206,7 @@
t = replacetext(t, "\[list\]", "")
t = replacetext(t, "\[/list\]", "")
t = "<font face=\"[CRAYON_FONT]\" color=[P.colour]><b>[t]</b></font>"
t = "<font face=\"[CRAYON_FONT]\" color=[C.paint_color]><b>[t]</b></font>"
// t = replacetext(t, "#", "") // Junk converted to nothing!
+69 -100
View File
@@ -631,7 +631,7 @@
/obj/machinery/power/apc/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, "apc.tmpl", name, 550, 550)
ui = new(user, src, ui_key, "apc", name, 550, 550)
ui.open()
/obj/machinery/power/apc/get_ui_data(mob/user)
@@ -721,22 +721,8 @@
/obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic()
if (IsAdminGhost(user))
if(IsAdminGhost(user))
return 1
if (user.stat)
user << "<span class='warning'>You must be conscious to use [src]!</span>"
return 0
if(!user.client)
return 0
if(!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to use [src]!</span>"
return 0
if(user.restrained())
user << "<span class='warning'>You must have free hands to use [src].</span>"
return 0
if(user.lying)
user << "<span class='warning'>You must stand to use [src]!</span>"
return 0
if(user.has_unlimited_silicon_privilege)
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
@@ -754,98 +740,81 @@
else
if ((!in_range(src, user) || !istype(src.loc, /turf)))
return 0
var/mob/living/carbon/human/H = user
if (istype(H))
if(H.getBrainLoss() >= 60)
H.visible_message("[H] stares cluelessly at [src] and drools.")
return 0
else if(prob(H.getBrainLoss()))
user << "<span class='danger'>You momentarily forget how to use [src].</span>"
return 0
return 1
/obj/machinery/power/apc/Topic(href, href_list)
/obj/machinery/power/apc/ui_act(action, params)
if(..())
return
if(!can_use(usr, 1))
return
if (href_list["lock"])
coverlocked = !coverlocked
else if (href_list["breaker"])
toggle_breaker()
else if (href_list["cmode"])
chargemode = !chargemode
if(!chargemode)
charging = 0
update_icon()
else if (href_list["eqp"])
var/val = text2num(href_list["eqp"])
equipment = setsubsystem(val)
update_icon()
update()
else if (href_list["lgt"])
var/val = text2num(href_list["lgt"])
lighting = setsubsystem(val)
update_icon()
update()
else if (href_list["env"])
var/val = text2num(href_list["env"])
environ = setsubsystem(val)
update_icon()
update()
else if (href_list["overload"])
if(usr.has_unlimited_silicon_privilege)
src.overload_lighting()
else if (href_list["malfhack"])
var/mob/living/silicon/ai/malfai = usr
if(get_malf_status(malfai)==1)
if (malfai.malfhacking)
malfai << "You are already hacking an APC."
return 1
malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
malfai.malfhack = src
malfai.malfhacking = 1
sleep(600)
if(src)
if (!src.aidisabled)
malfai.malfhack = null
malfai.malfhacking = 0
locked = 1
if (ticker.mode.config_tag == "malfunction")
if (src.z == ZLEVEL_STATION) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs++
if(usr:parent)
src.malfai = usr:parent
else
src.malfai = usr
malfai << "Hack complete. The APC is now under your exclusive control."
update_icon()
else if (href_list["occupyapc"])
if(get_malf_status(usr))
malfoccupy(usr)
else if (href_list["deoccupyapc"])
if(get_malf_status(usr))
malfvacate()
else if (href_list["toggleaccess"])
if(usr.has_unlimited_silicon_privilege)
if(emagged || (stat & (BROKEN|MAINT)))
usr << "The APC does not respond to the command."
else
locked = !locked
switch(action)
if("lock")
coverlocked = !coverlocked
if ("breaker")
toggle_breaker()
if("chargemode")
chargemode = !chargemode
if(!chargemode)
charging = 0
update_icon()
if("channel")
if (params["eqp"])
var/val = text2num(params["eqp"])
equipment = setsubsystem(val)
update_icon()
update()
else if (params["lgt"])
var/val = text2num(params["lgt"])
lighting = setsubsystem(val)
update_icon()
update()
else if (params["env"])
var/val = text2num(params["env"])
environ = setsubsystem(val)
update_icon()
update()
if("toggleaccess")
if(usr.has_unlimited_silicon_privilege)
if(emagged || (stat & (BROKEN|MAINT)))
usr << "The APC does not respond to the command."
else
locked = !locked
update_icon()
if("overload")
if(usr.has_unlimited_silicon_privilege)
src.overload_lighting()
if("hack")
var/mob/living/silicon/ai/malfai = usr
if(get_malf_status(malfai)==1)
if (malfai.malfhacking)
malfai << "You are already hacking an APC."
return 1
malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
malfai.malfhack = src
malfai.malfhacking = 1
sleep(600)
if(src)
if (!src.aidisabled)
malfai.malfhack = null
malfai.malfhacking = 0
locked = 1
if (ticker.mode.config_tag == "malfunction")
if (src.z == ZLEVEL_STATION) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs++
if(usr:parent)
src.malfai = usr:parent
else
src.malfai = usr
malfai << "Hack complete. The APC is now under your exclusive control."
update_icon()
if("occupy")
if(get_malf_status(usr))
malfoccupy(usr)
if("deoccupy")
if(get_malf_status(usr))
malfvacate()
return 1
/obj/machinery/power/apc/proc/toggle_breaker()
+1 -1
View File
@@ -61,7 +61,7 @@
return
/obj/singularity/narsie/proc/godsmack(atom/A)
if(istype(A,/obj/))
if(isobj(A))
var/obj/O = A
O.ex_act(1)
if(O) qdel(O)
@@ -246,7 +246,7 @@
/obj/singularity/proc/consume(atom/A)
var/gain = A.singularity_act(current_size)
var/gain = A.singularity_act(current_size, src)
src.energy += gain
if(istype(A, /obj/machinery/power/supermatter_shard) && !consumedSupermatter)
desc = "[initial(desc)] It glows fiercely with inner fire."
+44 -57
View File
@@ -327,7 +327,7 @@
/obj/machinery/power/smes/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, "smes.tmpl", name, 500, 400)
ui = new(user, src, ui_key, "smes", name, 500, 455)
ui.open()
/obj/machinery/power/smes/get_ui_data()
@@ -350,65 +350,52 @@
)
return data
/obj/machinery/power/smes/Topic(href, href_list)
/obj/machinery/power/smes/ui_act(action, params)
if(..())
return
if( href_list["input_attempt"] )
input_attempt = text2num(href_list["input_attempt"])
if(!input_attempt)
inputting = 0
log_smes(usr.ckey)
update_icon()
else if( href_list["output_attempt"] )
output_attempt = text2num(href_list["output_attempt"])
if(!output_attempt)
outputting = 0
log_smes(usr.ckey)
update_icon()
else if( href_list["set_input_level"] )
switch(href_list["set_input_level"])
if("max")
input_level = input_level_max
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to charge at? Max is [input_level_max].") as null|num
if(isnum(custom))
href_list["set_input_level"] = custom
.()
if("plus")
input_level += 10000
if("minus")
input_level -= 10000
else
var/n = text2num(href_list["set_input_level"])
if(isnum(n))
input_level = n
input_level = Clamp(input_level, 0, input_level_max)
log_smes(usr.ckey)
else if(href_list["set_output_level"])
switch(href_list["set_output_level"])
if("max")
output_level = output_level_max
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to output at? Max is [output_level_max].") as null|num
if(isnum(custom))
href_list["set_output_level"] = custom
.()
if("plus")
output_level += 10000
if("minus")
output_level -= 10000
else
var/n = text2num(href_list["set_output_level"])
if(isnum(n))
output_level = n
output_level = Clamp(output_level, 0, output_level_max)
log_smes(usr.ckey)
switch(action)
if("tryinput")
input_attempt = !input_attempt
log_smes(usr.ckey)
update_icon()
if("tryoutput")
output_attempt = !output_attempt
log_smes(usr.ckey)
update_icon()
if("input")
switch(params["set"])
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to charge at? Max is [input_level_max].") as null|num
if(custom)
input_level = custom
if("min")
input_level = 0
if("max")
input_level = input_level_max
if("plus")
input_level += 10000
if("minus")
input_level -= 10000
input_level = Clamp(input_level, 0, input_level_max)
log_smes(usr.ckey)
if("output")
switch(params["set"])
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to output at? Max is [output_level_max].") as null|num
if(custom)
output_level = custom
if("min")
output_level = 0
if("max")
output_level = output_level_max
if("plus")
output_level += 10000
if("minus")
output_level -= 10000
output_level = Clamp(output_level, 0, output_level_max)
log_smes(usr.ckey)
return 1
/obj/machinery/power/smes/proc/log_smes(user = "")
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Charge: [charge] | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [user]","singulo")
+29 -28
View File
@@ -372,7 +372,7 @@
/obj/machinery/power/solar_control/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, "solar_control.tmpl", name, 490, 395)
ui = new(user, src, ui_key, "solar_control", name, 515, 425)
ui.open()
/obj/machinery/power/solar_control/get_ui_data()
@@ -437,38 +437,39 @@
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
nexttime += 36000/abs(trackrate) //reset the counter for the next 1°
/obj/machinery/power/solar_control/Topic(href, href_list)
/obj/machinery/power/solar_control/ui_act(action, params)
if(..())
return
if(href_list["rate_control"])
if(href_list["cdir"])
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
src.targetdir = src.cdir
if(track == 2) //manual update, so losing auto-tracking
track = 0
spawn(1)
set_panels(cdir)
if(href_list["tdir"])
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
if(href_list["track"])
track = text2num(href_list["track"])
if(track == 2)
if(connected_tracker)
switch(action)
if("control")
if(params["cdir"])
src.cdir = dd_range(0,359,(360+src.cdir+text2num(params["cdir"]))%360)
src.targetdir = src.cdir
if(track == 2) //manual update, so losing auto-tracking
track = 0
spawn(1)
set_panels(cdir)
if(params["tdir"])
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(params["tdir"]))
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
if("tracking")
track = text2num(params["mode"])
if(track == 2)
if(connected_tracker)
connected_tracker.set_angle(SSsun.angle)
set_panels(cdir)
else if (track == 1) //begin manual tracking
src.targetdir = src.cdir
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
if("refresh")
search_for_connected()
if(connected_tracker && track == 2)
connected_tracker.set_angle(SSsun.angle)
set_panels(cdir)
else if (track == 1) //begin manual tracking
src.targetdir = src.cdir
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
set_panels(cdir)
return 1
if(href_list["search_connected"])
search_for_connected()
if(connected_tracker && track == 2)
connected_tracker.set_angle(SSsun.angle)
set_panels(cdir)
//rotates the panel to the passed angle
/obj/machinery/power/solar_control/proc/set_panels(cdir)
+117
View File
@@ -0,0 +1,117 @@
/obj/item/weapon/gun/medbeam
name = "Medical Beamgun"
desc = "Delivers medical nanites in a focused beam."
icon = 'icons/obj/chronos.dmi'
icon_state = "chronogun"
item_state = "chronogun"
w_class = 3.0
var/mob/living/current_target
var/last_check = 0
var/check_delay = 10 //Check los as often as possible, max resolution is SSobj tick though
var/max_range = 8
var/active = 0
var/datum/beam/current_beam = null
heavy_weapon = 1
/obj/item/weapon/gun/medbeam/New()
..()
SSobj.processing |= src
/obj/item/weapon/gun/medbeam/dropped(mob/user)
..()
LoseTarget()
/obj/item/weapon/gun/medbeam/proc/LoseTarget()
if(active)
qdel(current_beam)
active = 0
on_beam_release(current_target)
current_target = null
/obj/item/weapon/gun/medbeam/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override)
add_fingerprint(user)
if(!isliving(target))
return
if(current_target)
LoseTarget()
current_target = target
active = 1
current_beam = new(user,current_target,time=6000)
spawn(0)
current_beam.Start()
feedback_add_details("gun_fired","[src.type]")
/obj/item/weapon/gun/medbeam/afterattack(obj/target, mob/user, proximity)
if(target.loc == loc || target == user)
return
if(!current_target && isliving(target))
current_target = target
active = 1
current_beam = new(user,current_target,time=6000)
spawn(0)
current_beam.Start()
/obj/item/weapon/gun/medbeam/process()
var/mob/living/carbon/human/H = loc
if(!istype(H))
LoseTarget()
return
if(!current_target)
LoseTarget()
return
if(world.time <= last_check+check_delay)
return
last_check = world.time
if(get_dist(H,current_target)>max_range || !los_check(H,current_target))
LoseTarget()
H << "<span class='warning'>You lose control of the beam!</span>"
return
if(current_target)
on_beam_tick(current_target)
/obj/item/weapon/gun/medbeam/proc/los_check(mob/user,mob/target)
var/turf/user_turf = user.loc
if(!istype(user_turf))
return 0
var/obj/dummy = new(user_turf)
dummy.pass_flags |= PASSTABLE & PASSGLASS & PASSGRILLE //Grille/Glass so it can be used through common windows
for(var/turf/turf in getline(user_turf,target))
if(turf.density)
qdel(dummy)
return 0
for(var/atom/movable/AM in turf)
if(!AM.CanPass(dummy,turf,1))
qdel(dummy)
return 0
for(var/obj/effect/ebeam/medical/B in turf)// Don't cross the str-beams!
if(B.owner != current_beam)
explosion(B.loc,0,3,5,8)
qdel(dummy)
return 0
qdel(dummy)
return 1
/obj/item/weapon/gun/medbeam/proc/on_beam_hit(var/mob/living/target)
return
/obj/item/weapon/gun/medbeam/proc/on_beam_tick(var/mob/living/target)
target.adjustBruteLoss(-4)
target.adjustFireLoss(-4)
return
/obj/item/weapon/gun/medbeam/proc/on_beam_release(var/mob/living/target)
return
/obj/effect/ebeam/medical
name = "medical beam"
@@ -1,356 +1,354 @@
/obj/machinery/chem_dispenser
name = "chem dispenser"
desc = "Creates and dispenses chemicals."
density = 1
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "dispenser"
use_power = 1
idle_power_usage = 40
var/energy = 100
var/max_energy = 100
var/amount = 30
var/recharged = 0
var/recharge_delay = 5
var/image/icon_beaker = null
var/obj/item/weapon/reagent_containers/beaker = null
var/list/dispensable_reagents = list(
"hydrogen",
"lithium",
"carbon",
"nitrogen",
"oxygen",
"fluorine",
"sodium",
"aluminium",
"silicon",
"phosphorus",
"sulfur",
"chlorine",
"potassium",
"iron",
"copper",
"mercury",
"radium",
"water",
"ethanol",
"sugar",
"sacid",
"welding_fuel",
"silver",
"iodine",
"bromine",
"stable_plasma"
)
/obj/machinery/chem_dispenser/New()
..()
recharge()
dispensable_reagents = sortList(dispensable_reagents)
/obj/machinery/chem_dispenser/power_change()
if(powered())
stat &= ~NOPOWER
else
spawn(rand(0, 15))
stat |= NOPOWER
/obj/machinery/chem_dispenser/process()
if(recharged < 0)
recharge()
recharged = recharge_delay
else
recharged -= 1
/obj/machinery/chem_dispenser/proc/recharge()
if(stat & (BROKEN|NOPOWER)) return
var/addenergy = 1
var/oldenergy = energy
energy = min(energy + addenergy, max_energy)
if(energy != oldenergy)
use_power(2500)
/obj/machinery/chem_dispenser/ex_act(severity, target)
if(severity < 3)
..()
/obj/machinery/chem_dispenser/blob_act()
if(prob(50))
qdel(src)
/obj/machinery/chem_dispenser/interact(mob/user)
if(stat & BROKEN)
return
ui_interact(user)
/obj/machinery/chem_dispenser/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, "chem_dispenser.tmpl", name, 500, 650)
ui.open()
/obj/machinery/chem_dispenser/get_ui_data()
var/data = list()
data["amount"] = amount
data["energy"] = energy
data["maxEnergy"] = max_energy
data["isBeakerLoaded"] = beaker ? 1 : 0
var beakerContents[0]
var beakerCurrentVolume = 0
if(beaker && beaker.reagents && beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
beakerCurrentVolume += R.volume
data["beakerContents"] = beakerContents
if (beaker)
data["beakerCurrentVolume"] = beakerCurrentVolume
data["beakerMaxVolume"] = beaker.volume
data["beakerTransferAmounts"] = beaker.possible_transfer_amounts
else
data["beakerCurrentVolume"] = null
data["beakerMaxVolume"] = null
data["beakerTransferAmounts"] = null
var chemicals[0]
for(var/re in dispensable_reagents)
var/datum/reagent/temp = chemical_reagents_list[re]
if(temp)
chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("dispense" = temp.id)))) // list in a list because Byond merges the first list...
data["chemicals"] = chemicals
return data
/obj/machinery/chem_dispenser/Topic(href, href_list)
if(..())
return
if(href_list["amount"])
amount = round(text2num(href_list["amount"]), 5) // round to nearest 5
if (amount < 0) // Since the user can actually type the commands himself, some sanity checking
amount = 0
if (amount > 100)
amount = 100
if(href_list["dispense"])
if(beaker && dispensable_reagents.Find(href_list["dispense"]))
var/datum/reagents/R = beaker.reagents
var/space = R.maximum_volume - R.total_volume
R.add_reagent(href_list["dispense"], min(amount, energy * 10, space))
energy = max(energy - min(amount, energy * 10, space) / 10, 0)
if(href_list["remove"])
if(beaker)
var/amount = text2num(href_list["remove"])
if(isnum(amount) && (amount > 0) && (amount in beaker.possible_transfer_amounts))
beaker.reagents.remove_all(amount)
if(href_list["ejectBeaker"])
if(beaker)
beaker.loc = loc
beaker = null
overlays.Cut()
add_fingerprint(usr)
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
if(default_unfasten_wrench(user, I))
return
if(isrobot(user))
return
var/obj/item/weapon/reagent_containers/B = I // Get a beaker from it?
if(!istype(B))
return // Not a beaker?
if(beaker)
user << "<span class='warning'>A beaker is already loaded into the machine!</span>"
return
if(!user.drop_item()) // Can't let go?
return
beaker = B
beaker.loc = src
user << "<span class='notice'>You add the beaker to the machine.</span>"
if(!icon_beaker)
icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
icon_beaker.pixel_x = rand(-10,5)
overlays += icon_beaker
/obj/machinery/chem_dispenser/attack_hand(mob/user)
if (!user)
return
interact(user)
/obj/machinery/chem_dispenser/constructable
name = "portable chem dispenser"
icon = 'icons/obj/chemical.dmi'
icon_state = "minidispenser"
energy = 10
max_energy = 10
amount = 5
recharge_delay = 30
dispensable_reagents = list()
var/list/dispensable_reagent_tiers = list(
list(
"hydrogen",
"oxygen",
"silicon",
"phosphorus",
"sulfur",
"carbon",
"nitrogen",
"water"
),
list(
"lithium",
"sugar",
"sacid",
"copper",
"mercury",
"sodium",
"iodine",
"bromine"
),
list(
"ethanol",
"chlorine",
"potassium",
"aluminium",
"radium",
"fluorine",
"iron",
"welding_fuel",
"silver",
"stable_plasma"
),
list(
"oil",
"ash",
"acetone",
"saltpetre",
"ammonia",
"diethylamine"
)
)
/obj/machinery/chem_dispenser/constructable/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/chem_dispenser(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
RefreshParts()
/obj/machinery/chem_dispenser/constructable/RefreshParts()
var/time = 0
var/temp_energy = 0
var/i
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
temp_energy += M.rating
temp_energy--
max_energy = temp_energy * 5 //max energy = (bin1.rating + bin2.rating - 1) * 5, 5 on lowest 25 on highest
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
time += C.rating
for(var/obj/item/weapon/stock_parts/cell/P in component_parts)
time += round(P.maxcharge, 10000) / 10000
recharge_delay /= time/2 //delay between recharges, double the usual time on lowest 50% less than usual on highest
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
for(i=1, i<=M.rating, i++)
dispensable_reagents |= dispensable_reagent_tiers[i]
dispensable_reagents = sortList(dispensable_reagents)
/obj/machinery/chem_dispenser/constructable/attackby(var/obj/item/I, var/mob/user, params)
..()
if(default_deconstruction_screwdriver(user, "minidispenser-o", "minidispenser", I))
return
if(exchange_parts(user, I))
return
if(panel_open)
if(istype(I, /obj/item/weapon/crowbar))
if(beaker)
beaker.loc = loc
beaker = null
default_deconstruction_crowbar(I)
return 1
/obj/machinery/chem_dispenser/drinks
name = "soda dispenser"
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "soda_dispenser"
amount = 10
dispensable_reagents = list(
"water",
"ice",
"coffee",
"cream",
"tea",
"icetea",
"cola",
"spacemountainwind",
"dr_gibb",
"space_up",
"tonic",
"sodawater",
"lemon_lime",
"sugar",
"orangejuice",
"limejuice",
"tomatojuice"
)
/obj/machinery/chem_dispenser/drinks/attackby(obj/item/I, mob/user)
if(default_unfasten_wrench(user, I))
return
if (istype(I, /obj/item/weapon/reagent_containers/glass) || \
istype(I, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass) || \
istype(I, /obj/item/weapon/reagent_containers/food/drinks/shaker))
if (beaker)
return 1
else
if(!user.drop_item())
return 1
src.beaker = I
beaker.loc = src
update_icon()
return
/obj/machinery/chem_dispenser/drinks/beer
name = "booze dispenser"
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "booze_dispenser"
dispensable_reagents = list(
"lemon_lime",
"sugar",
"orangejuice",
"limejuice",
"sodawater",
"tonic",
"beer",
"kahlua",
"whiskey",
"wine",
"vodka",
"gin",
"rum",
"tequila",
"vermouth",
"cognac",
"ale"
)
/obj/machinery/chem_dispenser
name = "chem dispenser"
desc = "Creates and dispenses chemicals."
density = 1
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "dispenser"
use_power = 1
idle_power_usage = 40
interact_offline = 1
var/energy = 100
var/max_energy = 100
var/amount = 30
var/recharged = 0
var/recharge_delay = 5
var/image/icon_beaker = null
var/obj/item/weapon/reagent_containers/beaker = null
var/list/dispensable_reagents = list(
"hydrogen",
"lithium",
"carbon",
"nitrogen",
"oxygen",
"fluorine",
"sodium",
"aluminium",
"silicon",
"phosphorus",
"sulfur",
"chlorine",
"potassium",
"iron",
"copper",
"mercury",
"radium",
"water",
"ethanol",
"sugar",
"sacid",
"welding_fuel",
"silver",
"iodine",
"bromine",
"stable_plasma"
)
/obj/machinery/chem_dispenser/New()
..()
recharge()
dispensable_reagents = sortList(dispensable_reagents)
/obj/machinery/chem_dispenser/power_change()
if(powered())
stat &= ~NOPOWER
else
spawn(rand(0, 15))
stat |= NOPOWER
/obj/machinery/chem_dispenser/process()
if(recharged < 0)
recharge()
recharged = recharge_delay
else
recharged -= 1
/obj/machinery/chem_dispenser/proc/recharge()
if(stat & (BROKEN|NOPOWER)) return
var/addenergy = 1
var/oldenergy = energy
energy = min(energy + addenergy, max_energy)
if(energy != oldenergy)
use_power(2500)
/obj/machinery/chem_dispenser/ex_act(severity, target)
if(severity < 3)
..()
/obj/machinery/chem_dispenser/blob_act()
if(prob(50))
qdel(src)
/obj/machinery/chem_dispenser/interact(mob/user)
if(stat & BROKEN)
return
ui_interact(user)
/obj/machinery/chem_dispenser/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, "chem_dispenser", name, 530, 700)
ui.open()
/obj/machinery/chem_dispenser/get_ui_data()
var/data = list()
data["amount"] = amount
data["energy"] = energy
data["maxEnergy"] = max_energy
data["isBeakerLoaded"] = beaker ? 1 : 0
var beakerContents[0]
var beakerCurrentVolume = 0
if(beaker && beaker.reagents && beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
beakerCurrentVolume += R.volume
data["beakerContents"] = beakerContents
if (beaker)
data["beakerCurrentVolume"] = beakerCurrentVolume
data["beakerMaxVolume"] = beaker.volume
data["beakerTransferAmounts"] = beaker.possible_transfer_amounts
else
data["beakerCurrentVolume"] = null
data["beakerMaxVolume"] = null
data["beakerTransferAmounts"] = null
var chemicals[0]
for(var/re in dispensable_reagents)
var/datum/reagent/temp = chemical_reagents_list[re]
if(temp)
chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("reagent" = temp.id))))
data["chemicals"] = chemicals
return data
/obj/machinery/chem_dispenser/ui_act(action, params)
if(..())
return
switch(action)
if("amount")
amount = round(text2num(params["set"]), 5) // round to nearest 5
if (amount < 0) // Since the user can actually type the commands himself, some sanity checking
amount = 0
if (amount > 100)
amount = 100
if("dispense")
if(beaker && dispensable_reagents.Find(params["reagent"]))
var/datum/reagents/R = beaker.reagents
var/space = R.maximum_volume - R.total_volume
R.add_reagent(params["reagent"], min(amount, energy * 10, space))
energy = max(energy - min(amount, energy * 10, space) / 10, 0)
if("remove")
if(beaker)
var/amount = text2num(params["amount"])
if(isnum(amount) && (amount > 0) && (amount in beaker.possible_transfer_amounts))
beaker.reagents.remove_all(amount)
if("eject")
if(beaker)
beaker.loc = loc
beaker = null
overlays.Cut()
return 1
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
if(default_unfasten_wrench(user, I))
return
if(isrobot(user))
return
var/obj/item/weapon/reagent_containers/B = I // Get a beaker from it?
if(!istype(B))
return // Not a beaker?
if(beaker)
user << "<span class='warning'>A beaker is already loaded into the machine!</span>"
return
if(!user.drop_item()) // Can't let go?
return
beaker = B
beaker.loc = src
user << "<span class='notice'>You add the beaker to the machine.</span>"
if(!icon_beaker)
icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
icon_beaker.pixel_x = rand(-10,5)
overlays += icon_beaker
/obj/machinery/chem_dispenser/attack_hand(mob/user)
if (!user)
return
interact(user)
/obj/machinery/chem_dispenser/constructable
name = "portable chem dispenser"
icon = 'icons/obj/chemical.dmi'
icon_state = "minidispenser"
energy = 10
max_energy = 10
amount = 5
recharge_delay = 30
dispensable_reagents = list()
var/list/dispensable_reagent_tiers = list(
list(
"hydrogen",
"oxygen",
"silicon",
"phosphorus",
"sulfur",
"carbon",
"nitrogen",
"water"
),
list(
"lithium",
"sugar",
"sacid",
"copper",
"mercury",
"sodium",
"iodine",
"bromine"
),
list(
"ethanol",
"chlorine",
"potassium",
"aluminium",
"radium",
"fluorine",
"iron",
"welding_fuel",
"silver",
"stable_plasma"
),
list(
"oil",
"ash",
"acetone",
"saltpetre",
"ammonia",
"diethylamine"
)
)
/obj/machinery/chem_dispenser/constructable/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/chem_dispenser(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
RefreshParts()
/obj/machinery/chem_dispenser/constructable/RefreshParts()
var/time = 0
var/temp_energy = 0
var/i
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
temp_energy += M.rating
temp_energy--
max_energy = temp_energy * 5 //max energy = (bin1.rating + bin2.rating - 1) * 5, 5 on lowest 25 on highest
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
time += C.rating
for(var/obj/item/weapon/stock_parts/cell/P in component_parts)
time += round(P.maxcharge, 10000) / 10000
recharge_delay /= time/2 //delay between recharges, double the usual time on lowest 50% less than usual on highest
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
for(i=1, i<=M.rating, i++)
dispensable_reagents |= dispensable_reagent_tiers[i]
dispensable_reagents = sortList(dispensable_reagents)
/obj/machinery/chem_dispenser/constructable/attackby(var/obj/item/I, var/mob/user, params)
..()
if(default_deconstruction_screwdriver(user, "minidispenser-o", "minidispenser", I))
return
if(exchange_parts(user, I))
return
if(panel_open)
if(istype(I, /obj/item/weapon/crowbar))
if(beaker)
beaker.loc = loc
beaker = null
default_deconstruction_crowbar(I)
return 1
/obj/machinery/chem_dispenser/drinks
name = "soda dispenser"
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "soda_dispenser"
amount = 10
dispensable_reagents = list(
"water",
"ice",
"coffee",
"cream",
"tea",
"icetea",
"cola",
"spacemountainwind",
"dr_gibb",
"space_up",
"tonic",
"sodawater",
"lemon_lime",
"sugar",
"orangejuice",
"limejuice",
"tomatojuice"
)
/obj/machinery/chem_dispenser/drinks/attackby(obj/item/I, mob/user)
if(default_unfasten_wrench(user, I))
return
if (istype(I, /obj/item/weapon/reagent_containers/glass) || \
istype(I, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass) || \
istype(I, /obj/item/weapon/reagent_containers/food/drinks/shaker))
if (beaker)
return 1
else
if(!user.drop_item())
return 1
src.beaker = I
beaker.loc = src
update_icon()
return
/obj/machinery/chem_dispenser/drinks/beer
name = "booze dispenser"
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "booze_dispenser"
dispensable_reagents = list(
"lemon_lime",
"sugar",
"orangejuice",
"limejuice",
"sodawater",
"tonic",
"beer",
"kahlua",
"whiskey",
"wine",
"vodka",
"gin",
"rum",
"tequila",
"vermouth",
"cognac",
"ale"
)
@@ -1,134 +1,126 @@
/obj/machinery/chem_heater
name = "chemical heater"
density = 1
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0b"
use_power = 1
idle_power_usage = 40
var/obj/item/weapon/reagent_containers/beaker = null
var/desired_temp = 300
var/heater_coefficient = 0.10
var/on = FALSE
/obj/machinery/chem_heater/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/chem_heater(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
RefreshParts()
/obj/machinery/chem_heater/RefreshParts()
heater_coefficient = 0.10
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
heater_coefficient *= M.rating
/obj/machinery/chem_heater/process()
..()
if(stat & NOPOWER)
return
if(on)
if(beaker)
if(beaker.reagents.chem_temp > desired_temp)
beaker.reagents.chem_temp += min(-1, (desired_temp - beaker.reagents.chem_temp) * heater_coefficient)
if(beaker.reagents.chem_temp < desired_temp)
beaker.reagents.chem_temp += max(1, (desired_temp - beaker.reagents.chem_temp) * heater_coefficient)
beaker.reagents.chem_temp = round(beaker.reagents.chem_temp) //stops stuff like 456.12312312302
beaker.reagents.handle_reactions()
/obj/machinery/chem_heater/power_change()
if(powered())
stat &= ~NOPOWER
else
spawn(rand(0, 15))
stat |= NOPOWER
/obj/machinery/chem_heater/attackby(obj/item/I, mob/user, params)
if(isrobot(user))
return
if(istype(I, /obj/item/weapon/reagent_containers/glass))
if(beaker)
user << "<span class='warning'>A beaker is already loaded into the machine!</span>"
return
if(user.drop_item())
beaker = I
I.loc = src
user << "<span class='notice'>You add the beaker to the machine.</span>"
icon_state = "mixer1b"
if(default_deconstruction_screwdriver(user, "mixer0b", "mixer0b", I))
return
if(exchange_parts(user, I))
return
if(panel_open)
if(istype(I, /obj/item/weapon/crowbar))
eject_beaker()
default_deconstruction_crowbar(I)
return 1
/obj/machinery/chem_heater/attack_hand(mob/user)
if (!user)
return
interact(user)
/obj/machinery/chem_heater/Topic(href, href_list)
if(..())
return
if(href_list["toggle_on"])
on = !on
if(href_list["adjust_temperature"])
var/val = href_list["adjust_temperature"]
if(isnum(val))
desired_temp = Clamp(desired_temp+val, 0, 1000)
else if(val == "input")
desired_temp = Clamp(input("Please input the target temperature", name) as num, 0, 1000)
else
return
if(href_list["eject_beaker"])
eject_beaker()
add_fingerprint(usr)
/obj/machinery/chem_heater/interact(mob/user)
if(stat & BROKEN)
return
ui_interact(user)
/obj/machinery/chem_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, "chem_heater.tmpl", name, 350, 400)
ui.open()
/obj/machinery/chem_heater/get_ui_data()
var/data = list()
data["targetTemp"] = desired_temp
data["isActive"] = on
data["isBeakerLoaded"] = beaker ? 1 : 0
data["currentTemp"] = beaker ? beaker.reagents.chem_temp : null
data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null
data["beakerMaxVolume"] = beaker ? beaker.volume : null
var beakerContents[0]
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
data["beakerContents"] = beakerContents
return data
/obj/machinery/chem_heater/proc/eject_beaker()
if(beaker)
beaker.loc = get_turf(src)
beaker.reagents.handle_reactions()
beaker = null
/obj/machinery/chem_heater
name = "chemical heater"
density = 1
anchored = 1
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0b"
use_power = 1
idle_power_usage = 40
var/obj/item/weapon/reagent_containers/beaker = null
var/desired_temp = 300
var/heater_coefficient = 0.10
var/on = FALSE
/obj/machinery/chem_heater/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/chem_heater(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
RefreshParts()
/obj/machinery/chem_heater/RefreshParts()
heater_coefficient = 0.10
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
heater_coefficient *= M.rating
/obj/machinery/chem_heater/process()
..()
if(stat & NOPOWER)
return
if(on)
if(beaker)
if(beaker.reagents.chem_temp > desired_temp)
beaker.reagents.chem_temp += min(-1, (desired_temp - beaker.reagents.chem_temp) * heater_coefficient)
if(beaker.reagents.chem_temp < desired_temp)
beaker.reagents.chem_temp += max(1, (desired_temp - beaker.reagents.chem_temp) * heater_coefficient)
beaker.reagents.chem_temp = round(beaker.reagents.chem_temp) //stops stuff like 456.12312312302
beaker.reagents.handle_reactions()
/obj/machinery/chem_heater/power_change()
if(powered())
stat &= ~NOPOWER
else
spawn(rand(0, 15))
stat |= NOPOWER
/obj/machinery/chem_heater/attackby(obj/item/I, mob/user, params)
if(isrobot(user))
return
if(istype(I, /obj/item/weapon/reagent_containers/glass))
if(beaker)
user << "<span class='warning'>A beaker is already loaded into the machine!</span>"
return
if(user.drop_item())
beaker = I
I.loc = src
user << "<span class='notice'>You add the beaker to the machine.</span>"
icon_state = "mixer1b"
if(default_deconstruction_screwdriver(user, "mixer0b", "mixer0b", I))
return
if(exchange_parts(user, I))
return
if(panel_open)
if(istype(I, /obj/item/weapon/crowbar))
eject_beaker()
default_deconstruction_crowbar(I)
return 1
/obj/machinery/chem_heater/attack_hand(mob/user)
if (!user)
return
interact(user)
/obj/machinery/chem_heater/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
if("temperature")
desired_temp = Clamp(input("Please input the target temperature", name) as num, 0, 1000)
if("eject")
eject_beaker()
return 1
/obj/machinery/chem_heater/interact(mob/user)
if(stat & BROKEN)
return
ui_interact(user)
/obj/machinery/chem_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, "chem_heater", name, 350, 400)
ui.open()
/obj/machinery/chem_heater/get_ui_data()
var/data = list()
data["targetTemp"] = desired_temp
data["isActive"] = on
data["isBeakerLoaded"] = beaker ? 1 : 0
data["currentTemp"] = beaker ? beaker.reagents.chem_temp : null
data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null
data["beakerMaxVolume"] = beaker ? beaker.volume : null
var beakerContents[0]
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
data["beakerContents"] = beakerContents
return data
/obj/machinery/chem_heater/proc/eject_beaker()
if(beaker)
beaker.loc = get_turf(src)
beaker.reagents.handle_reactions()
beaker = null
icon_state = "mixer0b"
@@ -183,13 +183,10 @@
if (!M.stuttering) M.stuttering = 1
M.stuttering += 4
M.Dizzy(5)
if(iscultist(M) && prob(5))
M.say(pick("Av'te Nar'sie","Pa'lid Mors","INO INO ORA ANA","SAT ANA!","Daim'niodeis Arc'iai Le'eones","Egkau'haom'nai en Chaous","Ho Diak'nos tou Ap'iron","R'ge Na'sie","Diabo us Vo'iscum","Si gn'um Co'nu"))
if(data >= 75 && prob(33)) // 30 units, 135 seconds
if (!M.confused) M.confused = 1
M.confused += 3
if(iscultist(M) || (is_handofgod_cultist(M) && !is_handofgod_prophet(M)))
ticker.mode.remove_cultist(M.mind)
if((is_handofgod_cultist(M) && !is_handofgod_prophet(M)))
ticker.mode.remove_hog_follower(M.mind)
holder.remove_reagent(src.id, src.volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
M.jitteriness = 0
@@ -175,56 +175,28 @@
return..()
var/mob/living/simple_animal/SM = M
if(SM.sentience_type != sentience_type)
user << "<span class='warning'>The potion won't work on [M].</span>"
user << "<span class='warning'>The potion won't work on [SM].</span>"
return ..()
user << "<span class='notice'>You offer the sentience potion to [M]...</span>"
user << "<span class='notice'>You offer the sentience potion to [SM]...</span>"
being_used = 1
var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET)
shuffle(candidates)
var/time_passed = world.time
var/list/consenting_candidates = list()
for(var/candidate in candidates)
if(candidate in not_interested)
continue
spawn(0)
switch(alert(candidate, "Would you like to play as [M.name]? Please choose quickly!","Confirmation","Yes","No"))
if("Yes")
if((world.time-time_passed)>=50 || !src)
return
consenting_candidates += candidate
if("No")
if(!src)
return
not_interested += candidate
sleep(50)
if(!src)
return
listclearnulls(consenting_candidates) //some candidates might have left during sleep(50)
if(consenting_candidates.len)
var/client/C = null
C = pick(consenting_candidates)
M.key = C.key
M.languages |= HUMAN
M.faction -= "neutral"
M << "<span class='warning'>All at once it makes sense: you know what you are and who you are! Self awareness is yours!</span>"
M << "<span class='userdanger'>You are grateful to be self aware and owe [user] a great debt. Serve [user], and assist them in completing their goals at any cost.</span>"
user << "<span class='notice'>[M] accepts the potion and suddenly becomes attentive and aware. It worked!</span>"
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [SM.name]?", ROLE_ALIEN, null, ROLE_ALIEN, 50)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
SM.key = theghost.key
SM.languages |= HUMAN
SM.faction = user.faction
SM.sentience_act()
SM << "<span class='warning'>All at once it makes sense: you know what you are and who you are! Self awareness is yours!</span>"
SM << "<span class='userdanger'>You are grateful to be self aware and owe [user] a great debt. Serve [user], and assist them in completing their goals at any cost.</span>"
user << "<span class='notice'>[SM] accepts the potion and suddenly becomes attentive and aware. It worked!</span>"
qdel(src)
else
user << "<span class='notice'>[M] looks interested for a moment, but then looks back down. Maybe you should try again later.</span>"
user << "<span class='notice'>[SM] looks interested for a moment, but then looks back down. Maybe you should try again later.</span>"
being_used = 0
..()
+46
View File
@@ -55,6 +55,52 @@
-->
<div class="commit sansserif">
<h2 class="date">16 December 2015</h2>
<h3 class="author">AnturK updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Medical Beam Gun now available for Nuclear Operatives and ERT Medics.</li>
</ul>
<h3 class="author">Joan updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Revenant Overload Lights reveal time lowered from 10 seconds to 8 seconds, shock damage increased from 18 to 20.</li>
<li class="tweak">Revenant Blight reveal time lowered from 6 seconds to 5 seconds.</li>
</ul>
<h3 class="author">Kor updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Styptic once again works in patches.</li>
<li class="rscadd">Nuke Op team leaders can now activate challenge mode if more than 50 players are online.</li>
<li class="rscadd">Xenobio mobs will no longer spontaneously murder their friends if you give them sentience</li>
</ul>
<h3 class="author">The-Albinobigfoot updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">The Wishgranter now displays its faith in humans with curbed enthusiasm.</li>
</ul>
<h3 class="author">Tkdrg updated:</h3>
<ul class="changes bgimages16">
<li class="experiment">Cult has been overhauled in an attempt to make the gamemode more fun.</li>
<li class="rscdel">Cult onversion and stunpapers have been removed. So have most cult objectives.</li>
<li class="tweak">The cult's single objective is now defend and feed a large construct shell in order to summon the Geometer.</li>
<li class="tweak">The cult must sacrifice souls in order to acquire summoning orbs, which must be inserted inside said shell.</li>
<li class="tweak">The large construct shell can be procured by using a summoning orb in hand, but it is vulnerable to attack.</li>
<li class="tweak">Once enough orbs are inserted, the station will go Delta. After three minutes, the cult will have won.</li>
<li class="rscadd">Cult communications now no longer damage you when done without a tome.</li>
<li class="rscadd">Cultists now start with a sacrificial dagger, with bleeding effects and high throwing damage.</li>
<li class="rscadd">Most existing runes were buffed, merged, or removed. A Immolate rune and a Time Stop rune were added. Experiment!</li>
<li class="experiment">Each cultist now gets a random set of runes in their tomes. Pool together your knowledge in order to thrive.</li>
</ul>
<h3 class="author">neersighted updated:</h3>
<ul class="changes bgimages16">
<li class="experiment">NanoUI 3.0</li>
<li class="experiment">Completely rewrite NanoUI frontend; rework backend.</li>
<li class="tweak">Re-design NanoUI interface to be much more attractive.</li>
<li class="tweak">Reduce NanoUI LOC count/resource size.</li>
<li class="tweak">Reduce NanoUI tickrate; make UIs update properly.</li>
<li class="rscadd">Add chromeless NanoUI mode.</li>
<li class="rscadd">NanoUI's chromeless mode can be toggled with the 'Fancy NanoUI' preference.</li>
<li class="bugfix">Allow NanoUI to work on IE8-IE11, and Edge.</li>
<li class="bugfix">Close holes that allow NanoUI href spoofing.</li>
</ul>
<h2 class="date">15 December 2015</h2>
<h3 class="author">Incoming5643 updated:</h3>
<ul class="changes bgimages16">
+43
View File
@@ -2834,3 +2834,46 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
oranges:
- tweak: hulk no longer stuns
- tweak: John Cena
2015-12-16:
AnturK:
- rscadd: Medical Beam Gun now available for Nuclear Operatives and ERT Medics.
Joan:
- tweak: Revenant Overload Lights reveal time lowered from 10 seconds to 8 seconds,
shock damage increased from 18 to 20.
- tweak: Revenant Blight reveal time lowered from 6 seconds to 5 seconds.
Kor:
- rscadd: Styptic once again works in patches.
- rscadd: Nuke Op team leaders can now activate challenge mode if more than 50 players
are online.
- rscadd: Xenobio mobs will no longer spontaneously murder their friends if you
give them sentience
The-Albinobigfoot:
- bugfix: The Wishgranter now displays its faith in humans with curbed enthusiasm.
Tkdrg:
- experiment: Cult has been overhauled in an attempt to make the gamemode more fun.
- rscdel: Cult onversion and stunpapers have been removed. So have most cult objectives.
- tweak: The cult's single objective is now defend and feed a large construct shell
in order to summon the Geometer.
- tweak: The cult must sacrifice souls in order to acquire summoning orbs, which
must be inserted inside said shell.
- tweak: The large construct shell can be procured by using a summoning orb in hand,
but it is vulnerable to attack.
- tweak: Once enough orbs are inserted, the station will go Delta. After three minutes,
the cult will have won.
- rscadd: Cult communications now no longer damage you when done without a tome.
- rscadd: Cultists now start with a sacrificial dagger, with bleeding effects and
high throwing damage.
- rscadd: Most existing runes were buffed, merged, or removed. A Immolate rune and
a Time Stop rune were added. Experiment!
- experiment: Each cultist now gets a random set of runes in their tomes. Pool together
your knowledge in order to thrive.
neersighted:
- experiment: NanoUI 3.0
- experiment: Completely rewrite NanoUI frontend; rework backend.
- tweak: Re-design NanoUI interface to be much more attractive.
- tweak: Reduce NanoUI LOC count/resource size.
- tweak: Reduce NanoUI tickrate; make UIs update properly.
- rscadd: Add chromeless NanoUI mode.
- rscadd: NanoUI's chromeless mode can be toggled with the 'Fancy NanoUI' preference.
- bugfix: Allow NanoUI to work on IE8-IE11, and Edge.
- bugfix: Close holes that allow NanoUI href spoofing.
@@ -1,4 +0,0 @@
author: Kor
delete-after: True
changes:
- rscadd: "Styptic once again works in patches."
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Some files were not shown because too many files have changed in this diff Show More