You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio fequencies. Here is a step by step guide to start listening in on those saucy radio channels:
Equip yourself with a multi-tool
Use the multitool on each machine, that is the broadcaster, receiver and the relay.
Turn all the machines on, it has already been configured for you to listen on.
Simple as that. Now to listen to the private channels, you'll have to configure the intercoms, located on the front desk. Here is a list of frequencies for you to listen on.
The Captain assures me that there's nothing to worry about, but I find it hard to take a man who's paranoid of a powered shower door seriously.
- Comms Officer Vostok";
+ name = "personal log";
+ pixel_x = 26;
+ pixel_y = 4
+ },
+/obj/structure/computerframe{
+ desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
+ name = "decrepit computer"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aA" = (
+/obj/structure/table/reinforced,
+/obj/item/ashtray/bronze,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aB" = (
+/obj/machinery/computer/crew,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aC" = (
+/obj/structure/computerframe{
+ desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
+ name = "decrepit computer"
+ },
+/obj/item/shard,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aD" = (
+/obj/structure/closet/emcloset,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aE" = (
+/obj/structure/sign/nuke,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/bridge)
+"aF" = (
+/obj/item/twohanded/required/kirbyplants,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"aG" = (
+/obj/structure/safe/floor,
+/obj/item/paper/djstation{
+ name = "love letter";
+ pixel_x = -5;
+ pixel_y = -3;
+ layer = 2.9;
+ info = "To my darling Sergei,
I will never forget those nights we spent on Cygni, or all the times you took me around in your 2452 Vincent. The way you looked at me that one night, that was the night I knew that you and I were of the same soul.
I know they made you sell your Vincent when you were reassigned, but I could not let such a beautiful thing go to rust. I have made arrangements and it is here, waiting for you.
I have enclosed the keys. Please, let them serve as a reminder always of our love and a reason to return. I beg of you, do not let our love go softly into the night."
+ },
+/obj/item/key{
+ name = "Vincent '52 Key";
+ pixel_x = 0;
+ pixel_y = 0
+ },
+/obj/item/trash/tapetrash{
+ desc = "A bundle of severely yellowed and highly pretentious looking documents. Unfortunately they appear to be written in cyrillic and encrypted with a cypher.";
+ icon = 'icons/obj/bureaucracy.dmi';
+ icon_state = "docs_generic";
+ name = "USSP//NOFORN//TOP SECRET"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"aH" = (
+/obj/structure/coatrack,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"aI" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (WEST)";
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aJ" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aK" = (
+/obj/structure/chair/office/dark{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aL" = (
+/obj/structure/table/reinforced,
+/obj/item/phone{
+ desc = "An old Russian phone. The dial tone is still humming.";
+ name = "spin-dial phone"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aM" = (
+/obj/structure/chair/comfy/red{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aN" = (
+/obj/effect/landmark/damageturf,
+/obj/effect/landmark/burnturf,
+/obj/item/shard{
+ icon_state = "small"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aO" = (
+/obj/structure/table/reinforced,
+/obj/item/fan,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aP" = (
+/obj/structure/chair/office/dark{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aQ" = (
+/obj/effect/landmark/damageturf,
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"aR" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (EAST)";
+ icon_state = "tube1";
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aS" = (
+/obj/machinery/vending/cigarette/free{
+ slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.")
+ },
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aT" = (
+/obj/machinery/vending/sovietsoda,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aU" = (
+/obj/machinery/photocopier,
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (NORTH)";
+ icon_state = "tube1";
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"aV" = (
+/turf/simulated/wall/mineral/titanium/nodecon,
+/area/derelict/crew_quarters)
+"aW" = (
+/turf/simulated/wall/mineral/titanium/nodecon,
+/area/derelict/arrival)
+"aX" = (
+/obj/structure/closet{
+ icon_closed = "cabinet_closed";
+ icon_opened = "cabinet_open";
+ icon_state = "cabinet_closed"
+ },
+/obj/item/clothing/head/helmet/space/syndicate/blue{
+ desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
+ name = "Cosmonaut Command Helmet"
+ },
+/obj/item/clothing/suit/space/syndicate/blue{
+ desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
+ name = "Cosmonaut Command Suit"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"aY" = (
+/obj/structure/rack,
+/obj/item/gun/energy/e_gun/old{
+ desc = "A rudimentary energy weapon co-opted by the USSP from a TSF experimental prototype. There are two firing modes."
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"aZ" = (
+/obj/structure/table/wood,
+/obj/item/trash/can{
+ desc = "A miniature ship in a bottle. I wonder how they got it in there?";
+ icon = 'icons/obj/lavaland/artefacts.dmi';
+ icon_state = "ship_bottle";
+ name = "ship in a bottle"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"ba" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"bb" = (
+/turf/simulated/floor/carpet,
+/area/derelict/bridge)
+"bc" = (
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bd" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/bridge)
+"be" = (
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bf" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bg" = (
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bh" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bi" = (
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "dark";
+ tag = "icon-vault (NORTHEAST)"
+ },
+/area/derelict/bridge)
+"bj" = (
+/obj/item/paper/djstation{
+ info = "The note is stained with ink-smudges, the forceful and shaky handwriting scrawled across it is barely legible.
Vostok stopped banging on the door an hour ago. he must be looking for something to try and force it. I am still unsure what's happened, but it's been six hours now.
My hands won't stop shaking, not even the cigarettes are helping.
Vostok, if you manage to get in and I am no longer concious, my medication is in the freezer next to my desk. Please. I'm counting on you.";
+ name = "shaky note"
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bk" = (
+/obj/item/cigbutt{
+ pixel_x = 6;
+ pixel_y = 3
+ },
+/obj/item/cigbutt{
+ pixel_x = 8;
+ pixel_y = 9
+ },
+/obj/item/cigbutt,
+/obj/item/lighter{
+ pixel_x = -6;
+ pixel_y = 5
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bl" = (
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/vomit,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkblue"
+ },
+/area/derelict/bridge)
+"bm" = (
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/crew_quarters)
+"bn" = (
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/arrival)
+"bo" = (
+/obj/structure/cable{
+ d2 = 4;
+ icon_state = "0-4"
+ },
+/obj/machinery/power/apc/noalarm{
+ dir = 8;
+ pixel_x = -24
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"bp" = (
+/obj/structure/chair/comfy/red{
+ dir = 4
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/bridge)
+"bq" = (
+/obj/structure/table/wood,
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/obj/item/paper/djstation{
+ info = "This damned shower is going to be the death of me. I can see the way Vostok looks at me when I speak of it, the way his eyes sneer with amusement. Just this morning, I swear the damn thing tried to lock me in! I had to break the manual release just to get out, Vostok nearly shit himself he was laughing so hard.
I recognize the nature of this request my seem strange, but please, hear me out. Comrade Blyatski, though he is but a wee bot, is like iron fist of Commissar Grigor himself! Just the other day he chased that useless bastard Totstoi clean out of brig, you should have seen the way that drunkard whimpered! Like a dog with his tail between his legs.
Anyways, I digress! If any one is worth of recognition, it is our ever-vigilant and beloved Blyatski, true champion of USSP.
If you wish to, perhaps, see his vigilance and dedication in person, well! You need only come to inspect armoury.
Comrade Blyatski awaits your decision.";
+ name = "recommendation for commendation"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dD" = (
+/obj/structure/table/reinforced,
+/obj/structure/window/reinforced,
+/obj/machinery/door_control{
+ id = "ruslockcom";
+ name = "Bridge Lockdown"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dE" = (
+/obj/structure/table/reinforced,
+/obj/item/paper_bin,
+/obj/item/pen,
+/obj/structure/window/reinforced,
+/obj/machinery/newscaster{
+ desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. Strange that it's on a Russian station.";
+ layer = 3.3;
+ pixel_x = 27
+ },
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dF" = (
+/obj/structure/grille,
+/obj/structure/window/full/shuttle,
+/obj/machinery/door/poddoor/impassable{
+ id_tag = "ruslocksec";
+ layer = 2.9;
+ name = "Security Wing Lockdown"
+ },
+/turf/simulated/floor/plating,
+/area/derelict/arrival)
+"dG" = (
+/obj/structure/grille{
+ density = 0;
+ icon_state = "brokengrille"
+ },
+/obj/item/shard{
+ icon_state = "small"
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "floorscorched2"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"dH" = (
+/obj/structure/grille,
+/obj/structure/window/full/shuttle,
+/turf/simulated/floor/plating,
+/area/derelict/crew_quarters)
+"dI" = (
+/obj/machinery/door/airlock/shuttle{
+ name = "Dormitories"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/crew_quarters)
+"dJ" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel,
+/area/derelict/crew_quarters)
+"dK" = (
+/obj/structure/table/reinforced,
+/obj/structure/bedsheetbin,
+/obj/structure/sign/poster/contraband/random{
+ pixel_y = 32
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/crew_quarters)
+"dL" = (
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dM" = (
+/obj/structure/rack,
+/obj/item/crowbar,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dN" = (
+/obj/structure/closet,
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (EAST)";
+ icon_state = "tube1";
+ dir = 4
+ },
+/obj/item/clothing/head/ushanka,
+/obj/item/clothing/head/ushanka,
+/obj/item/clothing/head/ushanka,
+/obj/item/clothing/under/soviet,
+/obj/item/clothing/under/soviet,
+/obj/item/clothing/under/soviet,
+/obj/item/clothing/under/soviet,
+/obj/item/clothing/head/ushanka,
+/obj/item/clothing/head/ushanka,
+/obj/item/clothing/under/soviet,
+/turf/simulated/floor/plasteel,
+/area/derelict/crew_quarters)
+"dO" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkredfull"
+ },
+/turf/simulated/wall/mineral/titanium/nodecon/tileblend{
+ icon_state = "4-i"
+ },
+/area/derelict/arrival)
+"dP" = (
+/obj/item/clothing/under/retro/security,
+/obj/item/clothing/under/retro/security,
+/obj/structure/closet,
+/obj/item/clothing/gloves/combat,
+/obj/item/clothing/gloves/combat,
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ d2 = 2;
+ icon_state = "0-2";
+ pixel_y = 0
+ },
+/obj/machinery/power/apc/noalarm{
+ dir = 1;
+ pixel_y = 24
+ },
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dQ" = (
+/obj/machinery/recharger,
+/obj/structure/table/reinforced,
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (NORTH)";
+ icon_state = "tube1";
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dR" = (
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dS" = (
+/turf/simulated/wall/mineral/titanium/interior,
+/area/derelict/arrival)
+"dT" = (
+/obj/structure/closet,
+/obj/effect/spawner/lootdrop/maintenance,
+/obj/item/clothing/shoes/jackboots,
+/obj/item/clothing/shoes/jackboots,
+/obj/item/clothing/shoes/jackboots,
+/obj/item/clothing/shoes/jackboots,
+/obj/item/clothing/shoes/jackboots,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/clothing/head/panzer{
+ desc = "An oldschool military softcap.";
+ name = "old military cap"
+ },
+/obj/item/clothing/head/panzer{
+ desc = "An oldschool military softcap.";
+ name = "old military cap"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/crew_quarters)
+"dU" = (
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"dV" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2";
+ tag = ""
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"dW" = (
+/turf/simulated/wall/mineral/titanium/nodecon,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"dX" = (
+/obj/structure/sign/securearea,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"dY" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/door/poddoor/impassable{
+ id_tag = "ruslock";
+ layer = 3;
+ name = "Central Annex Lockdown"
+ },
+/obj/machinery/door/airlock/command/glass{
+ name = "Command Wing"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"dZ" = (
+/obj/structure/closet/crate/can,
+/obj/item/paper/crumpled{
+ info = "I KNOW IT WAS YOU WHO THREW AWAY MY LUCKY UNDERWEAR THIS TIME. I SWEAR, IF I SEE YOUR SKINNY RAT NECK AROUND I AM GOING TO WRING IT UNTIL YOU GO PURPLE!
I know it's you who's been feeding my cats alcohol, I do not care what your reasons are but you are getting in the way of important research. This is the fifth cat that I've had to replace this month because of your crude sense of humour, and I will be speaking with Chief Borachov if you don't stop.
- Nikolai Kartov, Deputy Researcher";
+ name = "Desist at once!"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fu" = (
+/obj/machinery/portable_atmospherics/scrubber,
+/obj/machinery/atmospherics/unary/portables_connector{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 5
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fv" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood,
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fw" = (
+/obj/structure/chair/wood{
+ dir = 4
+ },
+/turf/simulated/floor/wood{
+ tag = "icon-wood-broken3";
+ icon_state = "wood-broken3"
+ },
+/area/derelict/crew_quarters)
+"fx" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/structure/table/wood,
+/obj/item/trash/candle,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fy" = (
+/obj/effect/decal/cleanable/vomit,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fz" = (
+/obj/structure/mopbucket,
+/turf/simulated/floor/wood{
+ tag = "icon-wood-broken6";
+ icon_state = "wood-broken6"
+ },
+/area/derelict/crew_quarters)
+"fA" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"fB" = (
+/obj/item/trash/spentcasing{
+ icon_state = "762-casing"
+ },
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 4;
+ icon_state = "2-4";
+ tag = ""
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fC" = (
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fD" = (
+/obj/item/trash/spentcasing,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 8;
+ icon_state = "1-8";
+ tag = ""
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fE" = (
+/obj/structure/chair/office/dark,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/splatter,
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fF" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/computerframe{
+ desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
+ name = "decrepit computer"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"fG" = (
+/obj/structure/grille,
+/obj/structure/window/full/shuttle,
+/turf/simulated/floor/plating,
+/area/derelict/arrival)
+"fH" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fI" = (
+/obj/structure/table/tray,
+/obj/item/circular_saw{
+ pixel_y = 10
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fJ" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 8;
+ icon_state = "1-8"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fK" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fL" = (
+/obj/structure/sign/nosmoking_1,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fM" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkblue"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fN" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fO" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkblue"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fP" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (WEST)";
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fQ" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 4;
+ icon_state = "1-4"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fR" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fS" = (
+/obj/structure/computerframe{
+ desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
+ name = "decrepit computer"
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 5
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"fT" = (
+/obj/machinery/door_control{
+ id = "ruslock";
+ layer = 2.1;
+ name = "suspicious button"
+ },
+/obj/machinery/vending/cigarette/free{
+ slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.")
+ },
+/turf/simulated/floor/wood{
+ broken = 1;
+ icon_state = "wood-broken"
+ },
+/area/derelict/crew_quarters)
+"fU" = (
+/obj/item/trash/spentcasing,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fV" = (
+/obj/structure/chair/stool/bar,
+/obj/item/trash/spentcasing{
+ icon_state = "762-casing"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fW" = (
+/obj/structure/chair/stool/bar,
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/obj/effect/decal/cleanable/blood,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"fX" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fY" = (
+/obj/structure/table/reinforced,
+/obj/item/paper/djstation{
+ info = "August 21 - Most Excellent Commissar Grigor August 22 - Nobody August 23 - Nobody August 24 - Nobody August 25 - Why do I even bother? August 26 - Nobody August 27 -";
+ name = "visitor log"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"fZ" = (
+/obj/structure/table/reinforced,
+/obj/item/paper_bin,
+/obj/item/pen,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"ga" = (
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "gnawed bones"
+ },
+/obj/effect/decal/cleanable/blood/splatter,
+/obj/effect/decal/cleanable/blood/splatter,
+/mob/living/simple_animal/hostile/feral_cat{
+ faction = list("cat","carp");
+ name = "Experiment 432-A"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "purplecorner"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gb" = (
+/obj/machinery/door/window/eastleft{
+ locked = 1
+ },
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gc" = (
+/obj/structure/rack,
+/obj/item/clothing/gloves/color/latex/nitrile,
+/obj/item/clothing/gloves/color/latex/nitrile,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gd" = (
+/obj/structure/closet,
+/obj/item/clothing/under/retro/science,
+/obj/item/clothing/under/retro/science,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ge" = (
+/obj/effect/decal/cleanable/fungus,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gf" = (
+/obj/structure/chair/wood{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "darkblue"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gg" = (
+/obj/structure/table/wood,
+/obj/item/ashtray/plastic,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkblue"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gh" = (
+/obj/structure/chair/wood{
+ dir = 8
+ },
+/obj/structure/sign/poster/contraband/random{
+ pixel_x = 32
+ },
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkblue"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gi" = (
+/obj/machinery/floodlight,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gj" = (
+/obj/machinery/power/solar_control{
+ id = "russolar";
+ track = 2
+ },
+/obj/structure/cable{
+ icon_state = "0-2";
+ pixel_y = 1;
+ d2 = 2
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 4
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gk" = (
+/obj/structure/sign/poster/contraband/random,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gl" = (
+/obj/structure/chair/wood,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"gm" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"gn" = (
+/obj/structure/chair/stool/bar,
+/turf/simulated/floor/wood{
+ tag = "icon-wood-broken7";
+ icon_state = "wood-broken7"
+ },
+/area/derelict/crew_quarters)
+"go" = (
+/obj/structure/table/reinforced,
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gp" = (
+/obj/structure/table/reinforced,
+/obj/item/ashtray/bronze,
+/obj/item/cigbutt,
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gq" = (
+/obj/structure/chair{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"gr" = (
+/obj/item/trash/spentcasing,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"gs" = (
+/obj/structure/chair/stool,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"gt" = (
+/obj/structure/window/reinforced,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gu" = (
+/obj/structure/window/reinforced,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gv" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/structure/window/reinforced,
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gw" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gx" = (
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/obj/machinery/shower{
+ tag = "icon-shower (WEST)";
+ icon_state = "shower";
+ dir = 8
+ },
+/obj/structure/curtain/open/shower,
+/turf/simulated/floor/plasteel{
+ icon_state = "showroomfloor"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gy" = (
+/obj/effect/landmark/burnturf,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gz" = (
+/obj/machinery/recharge_station,
+/obj/effect/decal/cleanable/blood/oil,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gA" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gB" = (
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 8;
+ icon_state = "2-8"
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gC" = (
+/obj/structure/cable{
+ icon_state = "0-2";
+ pixel_y = 1;
+ d2 = 2
+ },
+/obj/machinery/power/apc/noalarm{
+ dir = 1;
+ pixel_y = 24
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gD" = (
+/obj/structure/rack,
+/obj/item/t_scanner,
+/obj/item/stack/cable_coil,
+/obj/item/stack/cable_coil,
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (NORTH)";
+ icon_state = "tube1";
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 5
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gE" = (
+/obj/structure/table/wood,
+/obj/item/ashtray/bronze,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"gF" = (
+/obj/structure/chair/wood{
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"gG" = (
+/obj/structure/chair/stool/bar,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"gH" = (
+/obj/item/trash/spentcasing,
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gI" = (
+/obj/structure/closet/secure_closet/bar,
+/obj/item/reagent_containers/food/drinks/bottle/vodka,
+/obj/item/reagent_containers/food/drinks/bottle/vodka,
+/obj/item/reagent_containers/food/drinks/bottle/vodka,
+/obj/item/reagent_containers/food/drinks/bottle/rum,
+/obj/item/reagent_containers/food/drinks/bottle/kahlua,
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gJ" = (
+/obj/effect/decal/cleanable/fungus,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/arrival)
+"gK" = (
+/obj/structure/chair{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"gL" = (
+/obj/effect/decal/cleanable/blood,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"gM" = (
+/obj/item/trash/spentcasing{
+ icon_state = "762-casing"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"gN" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"gO" = (
+/obj/structure/reagent_dispensers/fueltank,
+/obj/effect/decal/cleanable/blood/oil,
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gP" = (
+/obj/structure/table,
+/obj/item/storage/box/syringes,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gQ" = (
+/obj/structure/table,
+/obj/item/disk/data/demo{
+ pixel_x = -14;
+ pixel_y = -1
+ },
+/obj/item/paper/djstation{
+ info = "We have finally hit upon it, no more shall Katerina look past me in favor of other company! Experiment 432-A shows an incredible rate of cellular regeneration, and I posit that we have finally breaken down the great boundary between life and death--true biological immortality!
Of course, the aggressive behaviour is an undue side-effect, but it is only cat after all. I am certain a few sedative-laced cat treats will suffice to prep for autopsy.";
+ name = "Experiment 432-A"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gR" = (
+/mob/living/simple_animal/hostile/carp,
+/turf/template_noop,
+/area/space/nearstation)
+"gS" = (
+/obj/effect/landmark/damageturf,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gT" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 8;
+ icon_state = "1-8"
+ },
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 8;
+ icon_state = "2-8"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gU" = (
+/obj/item/clothing/under/retro/engineering,
+/obj/item/clothing/under/retro/engineering,
+/obj/structure/closet,
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 5
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"gV" = (
+/obj/structure/table/reinforced,
+/obj/item/reagent_containers/glass/rag,
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gW" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood{
+ amount = 0
+ },
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gX" = (
+/obj/structure/table/reinforced,
+/obj/item/wrench,
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (EAST)";
+ icon_state = "tube1";
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "grimy"
+ },
+/area/derelict/crew_quarters)
+"gY" = (
+/obj/machinery/power/solar{
+ id = "russolar"
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "solarpanel"
+ },
+/area/derelict/solar_control)
+"gZ" = (
+/obj/machinery/power/solar{
+ id = "russolar"
+ },
+/obj/structure/cable{
+ icon_state = "0-2";
+ pixel_y = 1;
+ d2 = 2
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "solarpanel"
+ },
+/area/derelict/solar_control)
+"ha" = (
+/obj/item/twohanded/required/kirbyplants,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"hb" = (
+/obj/machinery/light/spot,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/arrival)
+"hc" = (
+/obj/item/storage/box/cups,
+/obj/structure/table,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"hd" = (
+/obj/structure/reagent_dispensers/water_cooler,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkred"
+ },
+/area/derelict/arrival)
+"he" = (
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 4;
+ icon_state = "2-4"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"hf" = (
+/obj/structure/chair/office/light{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"hg" = (
+/obj/structure/computerframe,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"hh" = (
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "whiteredfull"
+ },
+/turf/simulated/wall/mineral/titanium/nodecon/tileblend{
+ fixed_underlay = list("icon" = 'icons/turf/floors.dmi', "icon_state" = "whiteredfull");
+ icon_state = "4-i"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"hi" = (
+/obj/effect/landmark/burnturf,
+/obj/structure/table/reinforced,
+/obj/item/stack/sheet/metal/fifty,
+/obj/item/stack/sheet/glass,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"hj" = (
+/obj/structure/table/reinforced,
+/obj/item/paper/djstation{
+ info = "This is the fifth time this month I've had to replace the cabling to the damn lockdown circuit. It's bad enough the condensor is constantly on the fritz and the damn systems take nearly a week to cycle and reboot, but now I've got the captain breathing down my neck over his stupid shower and Commissar Grigor. Mikail was telling me the man's face went so red when the lights popped that you could see him glowing in the dark.
If he thought that was bad, well, if I hadn't installed an override in the mess hall we would have been sitting in the dark for the week.
You will have to forgive me, but I am unable to get your order for one of those 'veil shifters' like you asked. I am admittedly unsure what you planned to do with it, the business of the clergy is not mine, but Vostok was quick to put the kaibosh on your order after we lost the last shipment.
The boys are still reeling from the headaches from last time, and Khoma complains that he sees the blue lights whenever he closes his eyes.
I am not one to question a man of God but I beg of you, please do not try to order any more of these artifacts. They are cursed, and all manner of demons seem to follow in their wake.
- Andrei Vostovich, Supply Technician";
+ name = "My apologies, father"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"hW" = (
+/obj/structure/table,
+/obj/item/flashlight/lamp,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"hX" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"hY" = (
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"hZ" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/item/trash/spentcasing,
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"ia" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/sign/poster/contraband/random{
+ pixel_x = 32
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"ib" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (WEST)";
+ icon_state = "tube1";
+ dir = 8
+ },
+/obj/structure/closet/l3closet/scientist,
+/obj/item/clothing/glasses/science,
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ic" = (
+/obj/structure/table/reinforced,
+/obj/item/clipboard,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"id" = (
+/obj/structure/chair/office/light,
+/turf/simulated/floor/plasteel,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ie" = (
+/obj/structure/closet/secure_closet/chemical,
+/obj/item/paper/djstation{
+ info = "A primitive rendition of a crying egg being stomped on by a boot has been scribbled in the right-hand margin of the paper.
Wahwahwah! True egghead! I do not give two shits about your cats or 'syence,' if you write to Chief I will tell that bitch Katerina about your baby boy crush.
Also, why you sign name on paper? I am next door, fuckhead, I know baby man note is yours as soon as I see it. You write girly letter like I am your lover, maybe if you spend less time in corner with cat you would be real man? Of course, you would still look like camel shit stuck to Totstoi's boot!";
+ name = "dear baby man"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"if" = (
+/obj/structure/grille,
+/obj/structure/window/full/shuttle,
+/turf/simulated/floor/plating,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ig" = (
+/obj/effect/landmark/damageturf,
+/obj/structure/flora/rock/pile,
+/turf/simulated/floor/plating/airless,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ih" = (
+/obj/item/stack/ore/iron,
+/turf/template_noop,
+/area/space/nearstation)
+"ii" = (
+/turf/template_noop,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ij" = (
+/obj/structure/closet/secure_closet/engineering_welding,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ik" = (
+/obj/structure/rack,
+/obj/item/clothing/head/helmet/space/syndicate/black/engie{
+ desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
+ name = "Cosmonaut Engineering Helmet"
+ },
+/obj/item/clothing/suit/space/syndicate/black/engie{
+ desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
+ name = "Cosmonaut Engineering Suit"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 5
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"il" = (
+/obj/structure/sign/poster/contraband/communist_state,
+/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
+/area/derelict/crew_quarters)
+"im" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"in" = (
+/obj/item/trash/spentcasing{
+ icon_state = "s-casing"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"io" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"ip" = (
+/obj/structure/table,
+/obj/item/storage/fancy/candle_box,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"iq" = (
+/obj/item/stack/tile,
+/turf/template_noop,
+/area/space/nearstation)
+"ir" = (
+/obj/structure/grille,
+/obj/structure/shuttle/window{
+ tag = "icon-window5_end";
+ icon = 'icons/turf/shuttle.dmi';
+ icon_state = "window5_end";
+ dir = 2
+ },
+/turf/simulated/floor/plating,
+/area/derelict/arrival)
+"is" = (
+/obj/structure/grille,
+/obj/structure/shuttle/window{
+ tag = "icon-window5_mid";
+ icon = 'icons/turf/shuttle.dmi';
+ icon_state = "window5_mid";
+ dir = 2
+ },
+/turf/simulated/floor/plating,
+/area/derelict/arrival)
+"it" = (
+/obj/structure/grille,
+/obj/structure/shuttle/window{
+ tag = "icon-window5_end (NORTH)";
+ icon = 'icons/turf/shuttle.dmi';
+ icon_state = "window5_end";
+ dir = 1
+ },
+/turf/simulated/floor/plating,
+/area/derelict/arrival)
+"iu" = (
+/turf/template_noop,
+/turf/simulated/shuttle/wall{
+ dir = 8;
+ icon_state = "diagonalWall3"
+ },
+/area/derelict/arrival)
+"iv" = (
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"iw" = (
+/obj/effect/decal/cleanable/blood/drip,
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"ix" = (
+/obj/effect/decal/cleanable/blood/splatter,
+/obj/item/trash/spentcasing{
+ icon_state = "s-casing"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"iy" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"iz" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (EAST)";
+ icon_state = "tube1";
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"iA" = (
+/obj/structure/closet/crate/can,
+/obj/effect/spawner/lootdrop/maintenance,
+/obj/item/paper/crumpled{
+ info = "This note has been crossed out so many times it's hard to make out its contents. Katerina,
Your eyes are like diamonds, Forged in the very fire of Cygni-A. My heart yearns for you, For your soft beauty Fuckfucknothat'sbad.
Your voice is like liquid gold, Smothering me in its delicate contours. Never before had I known, The touch, The touch! The touch of an angel's voice
note to self: stick to science, poetry is not my forte.";
+ name = "love poem"
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iB" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/fancy/vials,
+/obj/item/reagent_containers/glass/beaker{
+ pixel_x = 28
+ },
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iC" = (
+/obj/structure/table/reinforced,
+/obj/item/reagent_containers/glass/beaker{
+ pixel_x = 7;
+ pixel_y = 3
+ },
+/obj/item/reagent_containers/dropper{
+ pixel_y = 8
+ },
+/obj/structure/sign/poster/contraband/random{
+ pixel_y = -32
+ },
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iD" = (
+/turf/simulated/floor/engine{
+ name = "vacuum floor";
+ nitrogen = 0.01;
+ oxygen = 0.01
+ },
+/turf/simulated/wall/mineral/titanium/nodecon/tileblend{
+ fixed_underlay = list("icon" = 'icons/turf/floors.dmi', "icon_state" = "engine");
+ icon_state = "4-i"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iE" = (
+/turf/simulated/floor/engine{
+ name = "vacuum floor";
+ nitrogen = 0.01;
+ oxygen = 0.01
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iF" = (
+/turf/template_noop,
+/turf/simulated/shuttle/wall{
+ dir = 1;
+ icon_state = "diagonalWall3"
+ },
+/area/derelict/arrival)
+"iG" = (
+/obj/item/shard{
+ icon_state = "medium"
+ },
+/turf/template_noop,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iH" = (
+/obj/machinery/vending/assist,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iI" = (
+/obj/structure/closet/firecloset,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iJ" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"iK" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"iL" = (
+/obj/item/trash/spentcasing,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"iM" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"iN" = (
+/obj/machinery/atmospherics/unary/portables_connector,
+/obj/machinery/portable_atmospherics/canister/air,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/plasteel{
+ icon_state = "chapel"
+ },
+/area/derelict/crew_quarters)
+"iO" = (
+/turf/simulated/shuttle/wall{
+ dir = 4;
+ icon_state = "wall3"
+ },
+/area/derelict/arrival)
+"iP" = (
+/obj/structure/computerframe,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor4"
+ },
+/area/derelict/arrival)
+"iQ" = (
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor4"
+ },
+/area/derelict/arrival)
+"iR" = (
+/obj/structure/table,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/item/clothing/head/soft/solgov,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor4"
+ },
+/area/derelict/arrival)
+"iS" = (
+/obj/structure/closet/crate,
+/obj/effect/spawner/lootdrop/maintenance{
+ lootcount = 2;
+ name = "2maintenance loot spawner"
+ },
+/obj/structure/sign/poster/contraband/communist_state{
+ pixel_x = -32
+ },
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"iT" = (
+/obj/structure/closet/crate/trashcart,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"iU" = (
+/obj/effect/landmark/burnturf,
+/turf/simulated/floor/plasteel,
+/area/derelict/arrival)
+"iV" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "brown"
+ },
+/area/derelict/arrival)
+"iW" = (
+/obj/machinery/door/airlock/science{
+ name = "Science Wing"
+ },
+/obj/machinery/door/poddoor/impassable{
+ id_tag = "ruslock";
+ layer = 3;
+ name = "Central Annex Lockdown"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iX" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/door/airlock/science{
+ name = "Science Wing"
+ },
+/obj/machinery/door/poddoor/impassable{
+ id_tag = "ruslock";
+ layer = 3;
+ name = "Central Annex Lockdown"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "purple"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iY" = (
+/obj/structure/lattice,
+/obj/item/stack/ore/iron,
+/turf/template_noop,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"iZ" = (
+/obj/effect/landmark/damageturf,
+/obj/effect/decal/remains/human{
+ desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
+ icon_state = "remains";
+ name = "Human remains"
+ },
+/turf/simulated/floor/plating/airless,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ja" = (
+/obj/structure/lattice,
+/turf/template_noop,
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"jb" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/door/airlock/engineering{
+ name = "Engineering Wing"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "caution"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"jc" = (
+/obj/machinery/door/airlock/engineering{
+ name = "Engineering Wing"
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "caution";
+ dir = 4
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"jd" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/structure/chair/wood{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"je" = (
+/obj/structure/chair/wood{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"jf" = (
+/obj/effect/decal/cleanable/blood,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/derelict/crew_quarters)
+"jg" = (
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (EAST)";
+ icon_state = "tube1";
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/hidden,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/warning_stripes/southeastcorner,
+/turf/simulated/floor/plasteel{
+ icon_state = "wood"
+ },
+/area/derelict/crew_quarters)
+"jh" = (
+/turf/template_noop,
+/turf/simulated/wall/mineral/titanium/nodecon/nosmooth{
+ icon_state = "swall_f10"
+ },
+/area/derelict/eva{
+ name = "Derelict Annex"
+ })
+"ji" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor4"
+ },
+/area/derelict/arrival)
+"jj" = (
+/obj/item/paper/djstation{
+ info = "Fuck. Fuckfuckfuck. I knew this mission was a mistake, that idiot Thomas got himself killed by some angry Russian security bot in the armoury, and the Lt. ran into the annex like a moron and got himself trapped. Now I'm just sitting on my god damn hands because this shuttle won't bloody move. Stupid USSP piece of shit docking arm must be jammed and I don't have the kit to go out and fix it.
The Captain assures me that there's nothing to worry about, but I find it hard to take a man who's paranoid of a powered shower door seriously.
- Comms Officer Vostok";
- name = "personal log";
- pixel_x = 26;
- pixel_y = 4
- },
-/obj/structure/computerframe{
- desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
- name = "decrepit computer"
- },
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bh" = (
-/obj/effect/landmark/burnturf,
-/obj/structure/computerframe{
- desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
- name = "decrepit computer"
- },
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bi" = (
-/obj/machinery/computer/crew,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bj" = (
-/obj/structure/grille,
-/turf/space,
-/area/space/nearstation)
-"bk" = (
-/obj/structure/table/reinforced,
-/obj/item/ashtray/bronze,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bl" = (
-/obj/structure/closet/emcloset,
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bm" = (
-/obj/structure/computerframe{
- desc = "This computer is a husk of what it once was. Time and decay has worn its cheap circuitry to dust.";
- name = "decrepit computer"
- },
-/obj/item/shard,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bn" = (
-/turf/simulated/wall/mineral/titanium/nodecon,
-/area/derelict/crew_quarters)
-"bo" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/turf/simulated/wall/mineral/titanium/interior,
-/area/djstation)
-"bp" = (
-/obj/structure/cable{
- icon_state = "0-2";
- d2 = 2
- },
-/obj/machinery/power/smes/magical{
- desc = "A high-capacity superconducting magnetic energy storage (SMES) unit.";
- name = "power storage unit"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "vault";
- dir = 8
- },
-/area/djstation)
-"bq" = (
-/turf/space,
-/area/djstation/solars)
-"br" = (
-/obj/item/twohanded/required/kirbyplants,
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bs" = (
-/obj/structure/lattice,
-/obj/structure/grille,
-/turf/space,
-/area/space/nearstation)
-"bt" = (
-/turf/simulated/wall/mineral/titanium/nodecon,
-/area/derelict/arrival)
-"bu" = (
-/obj/structure/coatrack,
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bv" = (
-/obj/machinery/door/airlock/external{
- frequency = 1479;
- icon_state = "door_locked";
- id_tag = "dj_station_inner";
- locked = 1;
- name = "DJ Station Interior Access";
- req_access = null;
- req_access_txt = "0"
- },
-/obj/machinery/atmospherics/pipe/simple/hidden,
-/turf/simulated/floor/plating,
-/area/djstation)
-"bw" = (
-/obj/structure/safe/floor,
-/obj/item/paper/djstation{
- name = "love letter";
- pixel_x = -5;
- pixel_y = -3;
- layer = 2.9;
- info = "To my darling Sergei,
I will never forget those nights we spent on Cygni, or all the times you took me around in your 2452 Vincent. The way you looked at me that one night, that was the night I knew that you and I were of the same soul.
I know they made you sell your Vincent when you were reassigned, but I could not let such a beautiful thing go to rust. I have made arrangements and it is here, waiting for you.
I have enclosed the keys. Please, let them serve as a reminder always of our love and a reason to return. I beg of you, do not let our love go softly into the night."
- },
-/obj/item/key{
- name = "Vincent '52 Key";
- pixel_x = 0;
- pixel_y = 0
- },
-/obj/item/trash/tapetrash{
- desc = "A bundle of severely yellowed and highly pretentious looking documents. Unfortunately they appear to be written in cyrillic and encrypted with a cypher.";
- icon = 'icons/obj/bureaucracy.dmi';
- icon_state = "docs_generic";
- name = "USSP//NOFORN//TOP SECRET"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bx" = (
-/obj/machinery/light/spot{
- tag = "icon-tube1 (WEST)";
- icon_state = "tube1";
- dir = 8
- },
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"by" = (
-/obj/machinery/atmospherics/unary/vent_pump/high_volume{
- dir = 1;
- frequency = 1479;
- id_tag = "dj_station_pump"
- },
-/obj/machinery/airlock_sensor{
- frequency = 1479;
- id_tag = "dj_station_sensor";
- pixel_x = 25;
- pixel_y = -5
- },
-/obj/machinery/embedded_controller/radio/airlock/airlock_controller{
- frequency = 1479;
- id_tag = "dj_station_airlock";
- pixel_x = -25;
- req_access_txt = "0";
- tag_airpump = "dj_station_pump";
- tag_chamber_sensor = "dj_station_sensor";
- tag_exterior_door = "dj_station_outer";
- tag_interior_door = "dj_station_inner"
- },
-/obj/machinery/light/small{
- dir = 4
- },
-/turf/simulated/floor/plating,
-/area/djstation)
-"bz" = (
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/crew_quarters)
-"bA" = (
-/obj/machinery/door/airlock/external{
- frequency = 1479;
- icon_state = "door_locked";
- id_tag = "dj_station_outer";
- locked = 1;
- name = "DJ Station External Access";
- req_access = null;
- req_access_txt = "0"
- },
-/turf/simulated/floor/plating,
-/area/djstation)
-"bB" = (
-/obj/structure/chair/office/dark{
- dir = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bC" = (
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bD" = (
-/obj/structure/table/reinforced,
-/obj/item/phone{
- desc = "An old Russian phone. The dial tone is still humming.";
- name = "spin-dial phone"
- },
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bE" = (
-/obj/effect/landmark/damageturf,
-/obj/effect/landmark/burnturf,
-/obj/item/shard{
- icon_state = "small"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bF" = (
-/obj/structure/chair/comfy/red{
- dir = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bG" = (
-/obj/structure/chair/office/dark{
- dir = 4
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bH" = (
-/obj/structure/table/reinforced,
-/obj/item/fan,
-/turf/simulated/floor/plasteel{
- dir = 4;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bI" = (
-/obj/machinery/light/spot{
- tag = "icon-tube1 (EAST)";
- icon_state = "tube1";
- dir = 4
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 4;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bJ" = (
-/obj/effect/landmark/damageturf,
-/obj/effect/decal/remains/human{
- desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
- icon_state = "remains";
- name = "Human remains"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"bK" = (
-/obj/machinery/vending/cigarette/free{
- product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism."
- },
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bL" = (
-/obj/machinery/photocopier,
-/obj/machinery/light/spot{
- tag = "icon-tube1 (NORTH)";
- icon_state = "tube1";
- dir = 1
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bM" = (
-/obj/machinery/vending/sovietsoda,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bN" = (
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"bO" = (
-/obj/machinery/light/small{
- dir = 8
- },
-/obj/structure/dresser,
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "blue"
- },
-/area/derelict/crew_quarters)
-"bP" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/cable{
- d1 = 2;
- d2 = 4;
- icon_state = "2-4"
- },
-/turf/simulated/floor/plating,
-/area/djstation)
-"bQ" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/cable{
- d1 = 4;
- d2 = 8;
- icon_state = "4-8"
- },
-/turf/simulated/floor/plating,
-/area/djstation)
-"bR" = (
-/obj/structure/grille,
-/obj/structure/window/full/shuttle,
-/obj/structure/cable{
- d1 = 1;
- d2 = 4;
- icon_state = "1-4"
- },
-/obj/structure/cable{
- d1 = 4;
- d2 = 8;
- icon_state = "4-8"
- },
-/turf/simulated/floor/plating,
-/area/djstation)
-"bS" = (
-/obj/machinery/light/spot{
- tag = "icon-tube1 (NORTH)";
- icon_state = "tube1";
- dir = 1
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/item/twohanded/required/kirbyplants,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "darkblue"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"bT" = (
-/obj/structure/rack,
-/obj/item/gun/energy/e_gun/old{
- desc = "A rudimentary energy weapon co-opted by the USSP from a TSF experimental prototype. There are two firing modes."
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bU" = (
-/obj/structure/closet{
- icon_closed = "cabinet_closed";
- icon_opened = "cabinet_open";
- icon_state = "cabinet_closed"
- },
-/obj/item/clothing/head/helmet/space/syndicate/blue{
- desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
- name = "Cosmonaut Command Helmet"
- },
-/obj/item/clothing/suit/space/syndicate/blue{
- desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
- name = "Cosmonaut Command Suit"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bV" = (
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bW" = (
-/obj/structure/table/wood,
-/obj/item/trash/can{
- desc = "A miniature ship in a bottle. I wonder how they got it in there?";
- icon = 'icons/obj/lavaland/artefacts.dmi';
- icon_state = "ship_bottle";
- name = "ship in a bottle"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"bX" = (
-/turf/simulated/floor/carpet,
-/area/derelict/bridge)
-"bY" = (
-/obj/effect/decal/remains/human{
- desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
- icon_state = "remains";
- name = "Human remains"
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/vomit,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"bZ" = (
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"ca" = (
-/obj/structure/table,
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "blue"
- },
-/area/derelict/crew_quarters)
-"cb" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/bridge)
-"cc" = (
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"cd" = (
-/turf/simulated/floor/plasteel{
- dir = 10;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"ce" = (
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"cf" = (
-/turf/simulated/floor/plasteel{
- dir = 4;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"cg" = (
-/turf/simulated/floor/plasteel{
- dir = 5;
- icon_state = "dark";
- tag = "icon-vault (NORTHEAST)"
- },
-/area/derelict/bridge)
-"ch" = (
-/obj/item/cigbutt{
- pixel_x = 6;
- pixel_y = 3
- },
-/obj/item/cigbutt{
- pixel_x = 8;
- pixel_y = 9
- },
-/obj/item/cigbutt,
-/obj/item/lighter{
- pixel_x = -6;
- pixel_y = 5
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"ci" = (
-/obj/item/paper/djstation{
- info = "The note is stained with ink-smudges, the forceful and shaky handwriting scrawled across it is barely legible.
Vostok stopped banging on the door an hour ago. he must be looking for something to try and force it. I am still unsure what's happened, but it's been six hours now.
My hands won't stop shaking, not even the cigarettes are helping.
Vostok, if you manage to get in and I am no longer concious, my medication is in the freezer next to my desk. Please. I'm counting on you.";
- name = "shaky note"
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkblue"
- },
-/area/derelict/bridge)
-"cj" = (
-/obj/structure/sign/mech,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"ck" = (
-/obj/structure/cable{
- d2 = 4;
- icon_state = "0-4"
- },
-/obj/machinery/power/apc/noalarm{
- dir = 8;
- pixel_x = -24
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"cl" = (
-/obj/structure/cable{
- icon_state = "0-4";
- d2 = 4
- },
-/obj/machinery/power/apc/noalarm{
- dir = 0;
- name = "Worn-out APC";
- pixel_y = -24
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plating,
-/area/djstation)
-"cm" = (
-/obj/structure/grille,
-/obj/structure/window/full/shuttle,
-/turf/simulated/floor/plating,
-/area/djstation)
-"cn" = (
-/obj/structure/rack,
-/obj/item/clothing/suit/space/syndicate/orange{
- desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
- name = "Cosmonaut Security Suit"
- },
-/obj/item/clothing/head/helmet/space/syndicate/orange{
- desc = "This spacesuit is emblazoned with the emblem of the USSP. Glory to Space Russia!";
- name = "Cosmonaut Security Helmet"
- },
-/obj/item/clothing/mask/breath,
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plating,
-/area/djstation)
-"co" = (
-/obj/machinery/light_switch{
- pixel_y = -28
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plating,
-/area/djstation)
-"cp" = (
-/obj/structure/sign/securearea,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"cq" = (
-/obj/effect/decal/cleanable/fungus,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/crew_quarters)
-"cr" = (
-/obj/structure/chair/comfy/red{
- dir = 4
- },
-/obj/structure/cable{
- d1 = 4;
- d2 = 8;
- icon_state = "4-8"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"cs" = (
-/obj/item/clothing/under/retro/security,
-/obj/item/clothing/under/retro/security,
-/obj/structure/closet,
-/obj/item/clothing/gloves/combat,
-/obj/item/clothing/gloves/combat,
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/cable{
- d2 = 2;
- icon_state = "0-2";
- pixel_y = 0
- },
-/obj/machinery/power/apc/noalarm{
- dir = 1;
- pixel_y = 24
- },
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"ct" = (
-/obj/structure/chair/stool,
-/obj/structure/cable{
- d1 = 4;
- d2 = 8;
- icon_state = "4-8"
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/bridge)
-"cu" = (
-/obj/structure/table/wood,
-/obj/structure/cable{
- d1 = 4;
- d2 = 8;
- icon_state = "4-8"
- },
-/obj/item/paper/djstation{
- info = "This damned shower is going to be the death of me. I can see the way Vostok looks at me when I speak of it, the way his eyes sneer with amusement. Just this morning, I swear the damn thing tried to lock me in! I had to break the manual release just to get out, Vostok nearly shit himself he was laughing so hard.
You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio fequencies. Here is a step by step guide to start listening in on those saucy radio channels:
Equip yourself with a multi-tool
Use the multitool on each machine, that is the broadcaster, receiver and the relay.
Turn all the machines on, it has already been configured for you to listen on.
Simple as that. Now to listen to the private channels, you'll have to configure the intercoms, located on the front desk. Here is a list of frequencies for you to listen on.
I recognize the nature of this request my seem strange, but please, hear me out. Comrade Blyatski, though he is but a wee bot, is like iron fist of Commissar Grigor himself! Just the other day he chased that useless bastard Totstoi clean out of brig, you should have seen the way that drunkard whimpered! Like a dog with his tail between his legs.
Anyways, I digress! If any one is worth of recognition, it is our ever-vigilant and beloved Blyatski, true champion of USSP.
If you wish to, perhaps, see his vigilance and dedication in person, well! You need only come to inspect armoury.
Comrade Blyatski awaits your decision.";
- name = "recommendation for commendation"
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gk" = (
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/turf/simulated/wall/mineral/titanium/nodecon/tileblend{
- fixed_underlay = list("icon" = 'icons/turf/floors.dmi', "icon_state" = "dark");
- icon_state = "4-i"
- },
-/area/derelict/arrival)
-"gl" = (
-/obj/structure/table/reinforced,
-/obj/item/paper_bin,
-/obj/item/pen,
-/obj/structure/window/reinforced,
-/obj/machinery/newscaster{
- desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. Strange that it's on a Russian station.";
- layer = 3.3;
- pixel_x = 27
- },
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gm" = (
-/obj/structure/grille,
-/obj/structure/window/full/shuttle,
-/obj/machinery/door/poddoor/impassable{
- id_tag = "ruslocksec";
- layer = 2.9;
- name = "Security Wing Lockdown"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"gn" = (
-/obj/effect/landmark/damageturf,
-/obj/effect/decal/remains/human{
- desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
- icon_state = "remains";
- name = "Human remains"
- },
-/turf/simulated/floor/plating/airless,
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"go" = (
-/turf/space,
-/turf/simulated/wall/mineral/titanium/nodecon/nosmooth{
- icon_state = "swall_f10"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"gp" = (
-/obj/effect/landmark/damageturf,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gq" = (
-/obj/effect/landmark/burnturf,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gr" = (
-/obj/structure/grille,
-/obj/structure/window/full/shuttle,
-/turf/simulated/floor/plating,
-/area/derelict/crew_quarters)
-"gs" = (
-/obj/machinery/door/airlock/shuttle{
- name = "Dormitories"
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/crew_quarters)
-"gt" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel,
-/area/derelict/crew_quarters)
-"gu" = (
-/obj/structure/table/reinforced,
-/obj/structure/bedsheetbin,
-/obj/structure/sign/poster/contraband/random{
- pixel_y = 32
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/crew_quarters)
-"gv" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gw" = (
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gx" = (
-/obj/structure/rack,
-/obj/item/crowbar,
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gy" = (
-/turf/simulated/floor/plasteel{
- icon_state = "chapel"
- },
-/area/derelict/crew_quarters)
-"gz" = (
-/obj/structure/closet/medical_wall,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gA" = (
-/obj/structure/closet,
-/obj/machinery/light/spot{
- tag = "icon-tube1 (EAST)";
- icon_state = "tube1";
- dir = 4
- },
-/obj/item/clothing/head/ushanka,
-/obj/item/clothing/head/ushanka,
-/obj/item/clothing/head/ushanka,
-/obj/item/clothing/under/soviet,
-/obj/item/clothing/under/soviet,
-/obj/item/clothing/under/soviet,
-/obj/item/clothing/under/soviet,
-/obj/item/clothing/head/ushanka,
-/obj/item/clothing/head/ushanka,
-/obj/item/clothing/under/soviet,
-/turf/simulated/floor/plasteel,
-/area/derelict/crew_quarters)
-"gB" = (
-/obj/structure/closet/crate{
- icon_state = "crateopen";
- opened = 1
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/item/stack/packageWrap,
-/obj/item/stack/packageWrap,
-/obj/item/destTagger,
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "brown"
- },
-/area/derelict/arrival)
-"gC" = (
-/obj/machinery/recharger,
-/obj/structure/table/reinforced,
-/obj/machinery/light/spot{
- tag = "icon-tube1 (NORTH)";
- icon_state = "tube1";
- dir = 1
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 1;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gD" = (
-/obj/item/trash/spentcasing,
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/crew_quarters)
-"gE" = (
-/obj/effect/landmark/damageturf,
-/turf/simulated/floor/plating/airless,
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"gF" = (
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gG" = (
-/obj/structure/closet,
-/obj/effect/spawner/lootdrop/maintenance,
-/obj/item/clothing/shoes/jackboots,
-/obj/item/clothing/shoes/jackboots,
-/obj/item/clothing/shoes/jackboots,
-/obj/item/clothing/shoes/jackboots,
-/obj/item/clothing/shoes/jackboots,
-/obj/effect/decal/cleanable/dirt,
-/obj/item/clothing/head/panzer{
- desc = "An oldschool military softcap.";
- name = "old military cap"
- },
-/obj/item/clothing/head/panzer{
- desc = "An oldschool military softcap.";
- name = "old military cap"
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/crew_quarters)
-"gH" = (
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/turf/simulated/wall/mineral/titanium/nodecon/tileblend{
- fixed_underlay = list("icon" = 'icons/turf/floors.dmi', "icon_state" = "dark");
- icon_state = "4-i"
- },
-/area/djstation)
-"gI" = (
-/turf/space,
-/area/djstation)
-"gJ" = (
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"gK" = (
-/obj/structure/sign/greencross,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gL" = (
-/obj/structure/sign/vacuum,
-/turf/simulated/wall/mineral/titanium/nodecon/nodiagonal,
-/area/derelict/arrival)
-"gM" = (
-/obj/structure/chair/stool/bar,
-/obj/item/trash/spentcasing{
- icon_state = "762-casing"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "wood"
- },
-/area/derelict/crew_quarters)
-"gN" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/door/poddoor/impassable{
- id_tag = "ruslock";
- layer = 3;
- name = "Central Annex Lockdown"
- },
-/obj/machinery/door/airlock/command/glass{
- name = "Command Wing"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"gO" = (
-/obj/item/trash/spentcasing,
-/turf/simulated/floor/plasteel{
- icon_state = "grimy"
- },
-/area/derelict/crew_quarters)
-"gP" = (
-/obj/structure/closet/crate/can,
-/obj/item/paper/crumpled{
- info = "I KNOW IT WAS YOU WHO THREW AWAY MY LUCKY UNDERWEAR THIS TIME. I SWEAR, IF I SEE YOUR SKINNY RAT NECK AROUND I AM GOING TO WRING IT UNTIL YOU GO PURPLE!
I know it's you who's been feeding my cats alcohol, I do not care what your reasons are but you are getting in the way of important research. This is the fifth cat that I've had to replace this month because of your crude sense of humour, and I will be speaking with Chief Borachov if you don't stop.
Of course, the aggressive behaviour is an undue side-effect, but it is only cat after all. I am certain a few sedative-laced cat treats will suffice to prep for autopsy.";
- name = "Experiment 432-A"
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"jW" = (
-/turf/simulated/floor/plasteel{
- dir = 4;
- icon_state = "orange"
- },
-/area/derelict/crew_quarters)
-"jX" = (
-/obj/structure/table,
-/obj/effect/decal/cleanable/dirt,
-/obj/item/paper/djstation{
- info = "Father Gregor,
You will have to forgive me, but I am unable to get your order for one of those 'veil shifters' like you asked. I am admittedly unsure what you planned to do with it, the business of the clergy is not mine, but Vostok was quick to put the kaibosh on your order after we lost the last shipment.
The boys are still reeling from the headaches from last time, and Khoma complains that he sees the blue lights whenever he closes his eyes.
I am not one to question a man of God but I beg of you, please do not try to order any more of these artifacts. They are cursed, and all manner of demons seem to follow in their wake.
- Andrei Vostovich, Supply Technician";
- name = "My apologies, father"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/crew_quarters)
-"jY" = (
-/obj/item/trash/spentcasing{
- icon_state = "762-casing"
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/arrival)
-"jZ" = (
-/obj/item/beach_ball/holoball,
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "orange"
- },
-/area/derelict/crew_quarters)
-"ka" = (
-/obj/effect/landmark/damageturf,
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "caution"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"kb" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 8;
- icon_state = "1-8"
- },
-/obj/structure/cable{
- d1 = 2;
- d2 = 8;
- icon_state = "2-8"
- },
-/turf/simulated/floor/plasteel,
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"kc" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 9;
- icon_state = "redblue"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"kd" = (
-/obj/structure/table/reinforced,
-/obj/item/reagent_containers/glass/rag,
-/turf/simulated/floor/plasteel{
- icon_state = "grimy"
- },
-/area/derelict/crew_quarters)
-"ke" = (
-/obj/structure/table/reinforced,
-/obj/item/wrench,
-/obj/machinery/light/spot{
- tag = "icon-tube1 (EAST)";
- icon_state = "tube1";
- dir = 4
- },
-/turf/simulated/floor/plasteel{
- icon_state = "grimy"
- },
-/area/derelict/crew_quarters)
-"kf" = (
-/obj/effect/decal/cleanable/blood/drip,
-/obj/effect/decal/cleanable/blood{
- amount = 0
- },
-/obj/effect/decal/remains/human{
- desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
- icon_state = "remains";
- name = "Human remains"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "grimy"
- },
-/area/derelict/crew_quarters)
-"kg" = (
-/obj/machinery/power/solar{
- id = "russolar"
- },
-/turf/simulated/floor/plasteel/airless{
- icon_state = "solarpanel"
- },
-/area/derelict/solar_control)
-"kh" = (
-/obj/machinery/power/solar{
- id = "russolar"
- },
-/obj/structure/cable{
- icon_state = "0-2";
- pixel_y = 1;
- d2 = 2
- },
-/turf/simulated/floor/plasteel/airless{
- icon_state = "solarpanel"
- },
-/area/derelict/solar_control)
-"ki" = (
-/obj/item/twohanded/required/kirbyplants,
-/turf/simulated/floor/plasteel{
- dir = 10;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"kj" = (
-/obj/machinery/light/spot,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/derelict/arrival)
-"kk" = (
-/obj/item/storage/box/cups,
-/obj/structure/table,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"kl" = (
-/obj/structure/reagent_dispensers/water_cooler,
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "darkred"
- },
-/area/derelict/arrival)
-"km" = (
-/obj/structure/cable{
- d1 = 2;
- d2 = 4;
- icon_state = "2-4"
- },
-/turf/simulated/floor/plasteel{
- dir = 8;
- icon_state = "purple"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"kn" = (
-/obj/structure/chair/office/light{
- dir = 4
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel,
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"ko" = (
-/obj/structure/computerframe,
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "purple"
- },
-/area/derelict/eva{
- name = "Derelict Annex"
- })
-"kp" = (
-/obj/item/stack/ore/uranium,
-/turf/space,
-/area/space/nearstation)
-"kq" = (
-/obj/structure/table/reinforced,
-/obj/item/paper/djstation{
- info = "This is the fifth time this month I've had to replace the cabling to the damn lockdown circuit. It's bad enough the condensor is constantly on the fritz and the damn systems take nearly a week to cycle and reboot, but now I've got the captain breathing down my neck over his stupid shower and Commissar Grigor. Mikail was telling me the man's face went so red when the lights popped that you could see him glowing in the dark.
If he thought that was bad, well, if I hadn't installed an override in the mess hall we would have been sitting in the dark for the week.
Wahwahwah! True egghead! I do not give two shits about your cats or 'syence,' if you write to Chief I will tell that bitch Katerina about your baby boy crush.
Now who is laugh, cyka blyats? You idiots pissing yourselves in dark, but Totstoi clever and make escape. I have key to space, EVA gear. While you soil pants, I kiss your dumb asses goodbye!
Goodbyegoodbyegoodbyegoodbye, fuck you, and goodnight!";
- name = "I PISS ON YOU!"
- },
-/turf/space,
-/area/space/nearstation)
-"yo" = (
-/obj/structure/chair/comfy/brown{
- dir = 8
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yp" = (
-/turf/simulated/floor/plasteel{
- dir = 10;
- icon_state = "red"
- },
-/area/derelict/arrival)
-"yq" = (
-/obj/item/twohanded/required/kirbyplants,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yt" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "red"
- },
-/area/derelict/arrival)
-"yu" = (
-/obj/structure/table,
-/obj/item/flashlight/lamp,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yw" = (
-/turf/simulated/floor/plasteel{
- icon_state = "red"
- },
-/area/derelict/arrival)
-"yx" = (
-/turf/simulated/floor/plasteel{
- dir = 6;
- icon_state = "red"
- },
-/area/derelict/arrival)
-"yy" = (
-/obj/structure/table/wood/poker,
-/obj/item/deck/cards,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yz" = (
-/obj/structure/chair{
- dir = 4
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yB" = (
-/obj/structure/chair{
- dir = 8
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yC" = (
-/obj/structure/closet/crate/can,
-/obj/effect/spawner/lootdrop/maintenance{
- lootcount = 2;
- name = "2maintenance loot spawner"
- },
-/obj/item/trash/popcorn,
-/obj/item/trash/semki,
-/obj/item/paper/crumpled{
- info = "That idiot bastard Totstoi found my button. Stupid drunk was trying to put change into the free cigarette machine and dropped it. Lo' and behold, dumbass decides to look under the machine for his precious rubles.
Thankfully that green-livered swine cares more about drink than anything else, managed to buy him off. Will have to move the switch somewhere else now, but where?";
- name = "worn paper"
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yD" = (
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/flora/ausbushes/leafybush,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yE" = (
-/obj/structure/window/reinforced{
- dir = 8
- },
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/flora/ausbushes/fullgrass,
-/obj/structure/flora/ausbushes/ppflowers,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yF" = (
-/obj/structure/sign/poster/contraband/communist_state{
- pixel_y = -32
- },
-/obj/machinery/atmospherics/unary/portables_connector{
- dir = 4
- },
-/obj/machinery/portable_atmospherics/canister/air,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yG" = (
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/window/reinforced{
- tag = "icon-rwindow (EAST)";
- icon_state = "rwindow";
- dir = 4
- },
-/obj/structure/flora/ausbushes/ppflowers,
-/obj/structure/flora/ausbushes/sparsegrass,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yL" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/sign/poster/contraband/communist_state{
- pixel_y = -32
- },
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yN" = (
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/flora/ausbushes/fullgrass,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yO" = (
-/obj/structure/window/reinforced{
- dir = 8
- },
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/flora/ausbushes/ppflowers,
-/obj/structure/flora/ausbushes/leafybush,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yP" = (
-/obj/structure/table,
-/obj/machinery/computer/library/public,
-/turf/simulated/floor/plasteel{
- dir = 2;
- icon_state = "redfull";
- tag = "icon-redfull (NORTHWEST)"
- },
-/area/derelict/arrival)
-"yQ" = (
-/obj/structure/window/reinforced{
- tag = "icon-rwindow (EAST)";
- icon_state = "rwindow";
- dir = 4
- },
-/obj/structure/window/reinforced{
- dir = 1;
- layer = 2.9
- },
-/obj/structure/flora/ausbushes/ywflowers,
-/turf/simulated/floor/grass,
-/area/derelict/arrival)
-"yR" = (
-/obj/item/stack/cable_coil{
- amount = 1;
- max_amount = 30
- },
-/turf/space,
-/area/space/nearstation)
-"yS" = (
-/obj/machinery/door/airlock/external{
- frequency = 1501;
- id_tag = "rus_inner_1";
- name = "External Airlock";
- req_access_txt = "0"
- },
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/hidden,
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"yU" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/hidden,
-/obj/machinery/door/airlock/external{
- frequency = 1501;
- id_tag = "rus_inner_1";
- name = "External Airlock";
- req_access_txt = "0"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"yX" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/light/small{
- tag = "icon-bulb1 (EAST)";
- icon_state = "bulb1";
- dir = 4
- },
-/obj/machinery/atmospherics/unary/vent_pump/high_volume{
- dir = 1;
- frequency = 1501;
- id_tag = "rus_pump_1"
- },
-/obj/machinery/airlock_sensor{
- frequency = 1501;
- id_tag = "rus_sensor_1";
- pixel_x = 25;
- pixel_y = -5
- },
-/obj/machinery/embedded_controller/radio/airlock/airlock_controller{
- frequency = 1501;
- id_tag = "rus_airlock_1";
- pixel_x = -25;
- req_access_txt = "0";
- tag_airpump = "rus_pump_1";
- tag_chamber_sensor = "rus_sensor_1";
- tag_exterior_door = "rus_outer_1";
- tag_interior_door = "rus_inner_1"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"yZ" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/light/small{
- dir = 8
- },
-/obj/machinery/atmospherics/unary/vent_pump/high_volume{
- dir = 1;
- frequency = 1501;
- id_tag = "rus_pump_1"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"za" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/door/airlock/external{
- frequency = 1501;
- id_tag = "rus_outer_1";
- locked = 1;
- name = "External Airlock";
- req_access_txt = "0"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"zc" = (
-/obj/machinery/door/airlock/external{
- frequency = 1501;
- id_tag = "rus_outer_1";
- locked = 1;
- name = "External Airlock";
- req_access_txt = "0"
- },
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/turf/simulated/floor/plating,
-/area/derelict/arrival)
-"zf" = (
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/machinery/access_button{
- command = "cycle_exterior";
- frequency = 1501;
- master_tag = "rus_airlock_1";
- name = "exterior access button";
- pixel_y = 25;
- req_access_txt = "0"
- },
-/turf/space,
-/area/derelict/arrival)
-"zk" = (
-/obj/item/shard,
-/turf/space,
-/area/derelict/solar_control)
-"zl" = (
-/turf/space,
-/area/derelict/solar_control)
-"zm" = (
-/obj/item/shard{
- icon_state = "medium"
- },
-/turf/space,
-/area/derelict/solar_control)
-"zn" = (
-/obj/machinery/power/solar/fake,
-/obj/structure/cable,
-/obj/structure/cable,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "solarpanel"
- },
-/area/derelict/solar_control)
-"zo" = (
-/obj/structure/lattice,
-/turf/space,
-/area/derelict/solar_control)
-"zr" = (
-/obj/structure/cable,
-/obj/machinery/power/tracker,
-/obj/structure/cable,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "solarpanel"
- },
-/area/derelict/solar_control)
-"zs" = (
-/obj/structure/lattice,
-/obj/item/shard{
- icon_state = "small"
- },
-/turf/space,
-/area/space/nearstation)
-"zt" = (
-/turf/simulated/wall,
-/area/derelict/teleporter)
-"zu" = (
-/obj/structure/grille,
-/obj/structure/window/reinforced{
- dir = 5;
- max_integrity = 1e+007
- },
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zv" = (
-/obj/structure/grille{
- density = 0;
- icon_state = "brokengrille"
- },
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zw" = (
-/obj/structure/girder,
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zx" = (
-/turf/simulated/wall/rust,
-/area/derelict/teleporter)
-"zy" = (
-/obj/item/rack_parts,
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zz" = (
-/obj/effect/landmark/damageturf,
-/obj/item/shard{
- icon_state = "small"
- },
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zA" = (
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zB" = (
-/obj/machinery/light_construct/small{
- dir = 1
- },
-/obj/effect/landmark/damageturf,
-/obj/structure/filingcabinet/chestdrawer,
-/turf/simulated/floor/plasteel/airless{
- dir = 8;
- icon_state = "green"
- },
-/area/derelict/teleporter)
-"zC" = (
-/obj/machinery/light_construct/small{
- dir = 4
- },
-/obj/machinery/atmospherics/unary/portables_connector{
- layer = 2
- },
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zD" = (
-/obj/structure/table,
-/obj/item/clipboard,
-/turf/simulated/floor/plasteel/airless{
- dir = 8;
- icon_state = "green"
- },
-/area/derelict/teleporter)
-"zE" = (
-/obj/machinery/computer/teleporter,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "dark"
- },
-/area/derelict/teleporter)
-"zF" = (
-/obj/machinery/teleport/hub,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zG" = (
-/obj/machinery/teleport/station,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zH" = (
-/obj/machinery/atmospherics/pipe/simple/visible{
- dir = 5
- },
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zI" = (
-/obj/structure/door_assembly/door_assembly_ext{
- name = "Broken External Airlock"
- },
-/turf/simulated/floor/plating/airless,
-/area/derelict/teleporter)
-"zJ" = (
-/obj/structure/table,
-/obj/item/stock_parts/cell{
- charge = 100;
- maxcharge = 15000
- },
-/turf/simulated/floor/plasteel/airless{
- dir = 8;
- icon_state = "green"
- },
-/area/derelict/teleporter)
-"zK" = (
-/obj/effect/landmark/damageturf,
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zM" = (
-/obj/structure/sign/vacuum,
-/turf/simulated/wall,
-/area/derelict/teleporter)
-"zN" = (
-/obj/machinery/power/apc/noalarm{
- dir = 0;
- name = "Worn-out APC";
- pixel_y = -24
- },
-/turf/simulated/floor/plasteel/airless{
- icon_state = "floorgrime"
- },
-/area/derelict/teleporter)
-"zO" = (
-/obj/machinery/light/small,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/core)
-"zP" = (
-/obj/item/flag/chameleon{
- icon_state = "syndiflag";
- name = "Syndicate Flag";
- used = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/core)
-"zQ" = (
-/turf/simulated/mineral/random/labormineral,
-/turf/simulated/shuttle/wall{
- tag = "icon-swall_f5";
- icon_state = "swall_f5";
- dir = 2
- },
-/area/space/nearstation)
-"zR" = (
-/obj/machinery/portable_atmospherics/canister/toxins,
-/obj/machinery/light/small{
- dir = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/core)
-"zS" = (
-/obj/structure/cable{
- d1 = 1;
- d2 = 2;
- icon_state = "1-2"
- },
-/obj/machinery/light/small,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/core)
-"BB" = (
-/obj/structure/falsewall,
-/obj/structure/fans/tiny,
-/turf/simulated/floor/plating/airless,
-/area/syndicate_depot/outer)
-"DH" = (
-/obj/machinery/light{
- dir = 1;
- on = 1
- },
-/obj/item/flag/chameleon{
- icon_state = "syndiflag";
- name = "Syndicate Flag";
- used = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/core)
-"GF" = (
-/obj/item/flag/chameleon{
- icon_state = "syndiflag";
- name = "Syndicate Flag";
- used = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"GH" = (
-/obj/effect/spawner/random_spawners/syndicate/turret,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"Hg" = (
-/obj/structure/dispenser,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"KK" = (
-/obj/machinery/door/airlock/external{
- id_tag = "sst_away";
- req_access_txt = "150"
- },
-/obj/structure/fans/tiny,
-/turf/unsimulated/floor{
- name = "plating"
- },
-/area/syndicate_depot/outer)
-"Mc" = (
-/obj/machinery/door/poddoor{
- id_tag = "syndi_depot_rear";
- name = "Sealed Doors";
- protected = 0
- },
-/obj/machinery/door/airlock/external{
- id_tag = "sst_away";
- req_access_txt = "150"
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"OV" = (
-/obj/machinery/door/airlock/external{
- id_tag = "sst_away";
- req_access_txt = "150"
- },
-/obj/structure/fans/tiny,
-/turf/unsimulated/floor{
- name = "plating"
- },
-/area/syndicate_depot/core)
-"OX" = (
-/turf/simulated/wall/mineral/plastitanium/nodiagonal,
-/area/syndicate_depot/outer)
-"Pn" = (
-/obj/structure/table,
-/obj/effect/spawner/random_spawners/syndicate/loot/stetchkin,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"Sv" = (
-/obj/effect/spawner/random_spawners/blood_maybe,
-/turf/simulated/floor/plating/asteroid/airless,
-/area/syndicate_depot/outer)
-"UB" = (
-/obj/item/candle,
-/obj/structure/table,
-/turf/simulated/floor/plating/asteroid/airless,
-/area/syndicate_depot/outer)
-"UM" = (
-/obj/machinery/door_control{
- active_power_usage = 0;
- id = "syndi_depot_rear";
- idle_power_usage = 0;
- name = "mysterious button";
- normaldoorcontrol = 0;
- pixel_x = 24;
- use_power = 0
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"Yh" = (
-/obj/machinery/light{
- dir = 1;
- on = 1
- },
-/obj/machinery/portable_atmospherics/canister/oxygen,
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-"YV" = (
-/obj/structure/chair{
- dir = 8
- },
-/turf/simulated/floor/plating/asteroid/airless,
-/area/syndicate_depot/outer)
-"ZQ" = (
-/obj/machinery/turretid/syndicate{
- name = "external turret controls";
- pixel_x = -32;
- pixel_y = 0;
- req_access = list(150)
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/syndicate_depot/outer)
-
-(1,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(2,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(3,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(4,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(5,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(6,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(7,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(8,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(9,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(10,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(11,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(12,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(13,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(14,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(15,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(16,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(17,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(18,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(19,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(20,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(21,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(22,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(23,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(24,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(25,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(26,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(27,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(28,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(29,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(30,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(31,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mI
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(32,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lu
-lE
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(33,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lu
-mL
-lB
-lB
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mI
-mI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(34,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lt
-lw
-mp
-mP
-nb
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mI
-mI
-mI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(35,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lt
-lw
-mo
-az
-mQ
-mT
-mI
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mI
-mI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(36,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lt
-lw
-mq
-mP
-mQ
-mV
-mI
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(37,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lx
-mL
-lC
-lC
-lP
-mH
-mH
-mI
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mI
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(38,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lx
-lO
-mH
-mH
-mH
-mI
-mI
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(39,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-bj
-bj
-ai
-bj
-bj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mH
-aa
-aa
-aa
-lu
-mH
-mH
-na
-zQ
-mH
-mH
-mH
-mH
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(40,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-ae
-ae
-aa
-ae
-ae
-bj
-bj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-mH
-mW
-az
-mx
-mH
-mH
-mH
-mH
-mI
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(41,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-au
-ae
-aE
-aa
-aE
-ae
-ae
-bj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lu
-my
-mH
-nN
-nh
-np
-zQ
-mH
-mH
-mH
-mI
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(42,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-ae
-aE
-aQ
-aE
-aQ
-aE
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-mI
-nb
-nO
-az
-mY
-mx
-mH
-mH
-mH
-mI
-mI
-mI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(43,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-ae
-aE
-aQ
-aE
-aQ
-aE
-aa
-ax
-cm
-cm
-cm
-ax
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-nj
-mX
-az
-mD
-nl
-mx
-mH
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(44,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ai
-ae
-ac
-aR
-ac
-aQ
-aE
-aa
-ax
-aB
-ej
-eJ
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mL
-az
-az
-ng
-az
-az
-mL
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(45,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-bj
-aa
-ac
-aR
-ac
-aR
-aE
-aa
-ax
-dB
-aD
-eI
-ax
-ax
-ax
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mL
-az
-az
-nc
-nj
-az
-mL
-mH
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(46,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aS
-aa
-aS
-ae
-aa
-ax
-dD
-aD
-aD
-dd
-fE
-fY
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-mU
-az
-az
-az
-nm
-mx
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(47,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-aa
-bj
-ao
-bj
-aa
-aa
-aa
-aa
-aS
-aa
-aS
-ae
-ae
-ax
-dC
-aD
-aD
-ba
-fD
-fX
-dd
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-mU
-az
-nc
-az
-mU
-mx
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(48,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-ae
-aa
-ae
-aa
-aa
-aa
-aa
-aw
-aG
-aG
-bo
-ay
-cm
-ax
-dd
-ag
-ek
-ag
-dd
-ax
-ga
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-mz
-nc
-az
-az
-mU
-mx
-mH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(49,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-aa
-ae
-ac
-ac
-ac
-ac
-aa
-aa
-av
-aF
-ah
-am
-ah
-cl
-ax
-dc
-dE
-de
-eK
-fn
-gH
-ax
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mx
-az
-az
-nc
-nc
-az
-mx
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(50,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ai
-aa
-ac
-an
-an
-an
-an
-ap
-as
-ay
-aF
-ah
-ah
-ah
-ar
-ax
-df
-dF
-em
-eM
-fo
-fF
-gc
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lx
-mG
-mG
-mG
-mG
-mG
-lO
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(51,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-aa
-aa
-ac
-ac
-ac
-ac
-aa
-ae
-ax
-aH
-aj
-bp
-bP
-aq
-cK
-de
-df
-el
-eL
-fo
-de
-gb
-ax
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-mF
-ne
-ne
-ne
-nq
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(52,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-aa
-ac
-an
-an
-an
-an
-ap
-as
-aA
-ah
-ak
-ah
-bQ
-co
-ax
-dh
-dH
-en
-eO
-fo
-de
-dd
-ax
-ax
-gI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(53,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-ae
-ae
-ac
-ac
-ac
-ac
-ae
-aa
-av
-ah
-aU
-aF
-bQ
-cn
-ax
-dg
-dG
-de
-eN
-fp
-fG
-bv
-by
-bA
-hl
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(54,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-ae
-aa
-aa
-ae
-ae
-aa
-aa
-aC
-aG
-aG
-bo
-bR
-cm
-ax
-dd
-ag
-eo
-ag
-dd
-fH
-dd
-ax
-ax
-gI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(55,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-aa
-bj
-ai
-bj
-aa
-aa
-aa
-ae
-aS
-bq
-aS
-aa
-aa
-ax
-dI
-aO
-eP
-ax
-ax
-ax
-ae
-bs
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(56,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-ae
-ae
-aS
-bq
-aS
-aa
-aa
-ax
-dK
-aO
-eR
-ax
-aa
-aa
-bj
-bs
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(57,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-bj
-aa
-ac
-aT
-ac
-aT
-aE
-aa
-ax
-dJ
-aO
-eQ
-ax
-ae
-bs
-bs
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(58,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-ae
-bj
-aa
-ac
-aT
-ac
-aT
-aE
-aa
-ax
-dL
-aO
-aX
-ax
-bs
-bs
-ae
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(59,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-at
-ae
-aE
-aV
-aE
-aV
-aE
-aa
-ax
-cm
-cm
-cm
-ax
-aa
-ae
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(60,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-ae
-aE
-aV
-aE
-aV
-aE
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(61,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-ae
-ae
-aE
-aa
-aE
-ae
-ae
-bj
-aa
-aa
-aa
-ae
-ae
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(62,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-aa
-aa
-aa
-ae
-ae
-bj
-bj
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(63,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bj
-bj
-bj
-bj
-bj
-bj
-bj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(64,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(65,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-ae
-ae
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(66,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(67,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(68,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(69,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(70,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(71,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(72,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(73,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(74,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(75,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(76,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(77,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(78,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(79,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(80,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(81,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(82,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(83,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(84,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(85,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(86,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(87,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(88,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(89,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(90,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(91,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(92,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(93,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(94,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-zt
-zu
-zu
-zu
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(95,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-zt
-zt
-zB
-zD
-zJ
-zx
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(96,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-zs
-ae
-zt
-zy
-zA
-zA
-zK
-lL
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(97,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-lL
-zu
-lL
-zA
-zE
-lL
-zN
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(98,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-lL
-zv
-zA
-zA
-zG
-zA
-zA
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(99,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-ae
-ae
-lL
-zv
-zz
-zA
-zF
-zA
-zA
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(100,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-ae
-lL
-zx
-zA
-zA
-zA
-zA
-lL
-lL
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(101,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-ae
-ae
-ae
-ae
-zw
-lL
-zC
-zH
-tj
-zt
-zw
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(102,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-ae
-lL
-lL
-zt
-zI
-zM
-zt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(103,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-ae
-lL
-ae
-ae
-lL
-zw
-aa
-aa
-aa
-ly
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(104,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-lL
-ae
-ae
-lL
-zw
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(105,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-ae
-aa
-ae
-ae
-ae
-ae
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(106,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-ae
-ae
-aa
-aa
-al
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(107,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-ad
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(108,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-ae
-ae
-ae
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(109,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(110,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(111,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(112,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(113,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(114,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(115,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(116,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(117,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(118,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(119,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(120,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(121,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(122,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(123,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(124,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(125,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(126,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(127,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(128,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(129,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(130,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(131,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(132,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(133,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(134,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(135,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(136,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(137,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(138,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iC
-jO
-jO
-jO
-jO
-jO
-jO
-qQ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-yj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(139,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iD
-pS
-qr
-qT
-qT
-sl
-sD
-rs
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(140,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iL
-pV
-qt
-qs
-qs
-qs
-sD
-rs
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ly
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(141,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iW
-pU
-qs
-qU
-qU
-qs
-sE
-rs
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(142,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-jF
-jO
-qv
-jO
-jO
-qv
-jO
-sU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(143,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-qu
-bN
-bN
-sm
-bN
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(144,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bN
-pX
-qx
-qX
-rO
-gf
-sG
-bN
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(145,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-bN
-bN
-pW
-gf
-qW
-rN
-sn
-sF
-bN
-bN
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(146,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-eb
-bN
-bN
-gB
-lj
-pl
-gf
-hX
-gY
-jf
-gf
-gf
-ta
-ts
-fr
-bN
-bN
-fr
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(147,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-bN
-aW
-ju
-jP
-ki
-ei
-kT
-gf
-pk
-gf
-gf
-qY
-rP
-so
-gf
-jY
-tr
-bN
-tR
-ui
-uv
-fr
-bN
-fr
-sb
-aa
-gU
-aa
-aa
-aa
-wz
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-yR
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(148,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-ie
-iB
-gw
-fz
-hd
-fJ
-kD
-kV
-gf
-gf
-pZ
-gf
-rb
-rS
-gf
-gf
-gf
-pk
-tG
-tS
-uk
-tS
-uE
-uY
-uw
-qG
-uJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(149,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-bN
-bN
-ft
-fM
-fM
-fM
-fM
-kj
-bN
-kV
-gf
-hH
-gf
-gf
-iO
-rR
-qx
-pZ
-hH
-tt
-tF
-tS
-uj
-tT
-kG
-tS
-tS
-qK
-qS
-uJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(150,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-aW
-gV
-hh
-db
-if
-hG
-iX
-iX
-iX
-iX
-kF
-kX
-hD
-ll
-ll
-qz
-rd
-rU
-ll
-ll
-ll
-ll
-tI
-tU
-tU
-tU
-uG
-tS
-kG
-vC
-vB
-uJ
-uJ
-qc
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(151,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-aW
-gJ
-fM
-fM
-hE
-fM
-id
-fM
-fM
-gT
-kk
-bN
-kW
-lk
-po
-qa
-hZ
-rc
-rT
-sp
-qa
-po
-tu
-fw
-tT
-kz
-uw
-kI
-ql
-vl
-vB
-uJ
-uJ
-uJ
-qF
-uJ
-aa
-aa
-aa
-kZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(152,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-bt
-bN
-cs
-eE
-eE
-eE
-fx
-eE
-iA
-iZ
-fM
-jS
-kl
-bN
-bN
-bN
-bN
-bN
-qA
-rf
-rV
-sq
-bN
-bN
-bN
-bN
-tV
-ul
-tS
-qh
-qq
-uJ
-vD
-vB
-vW
-uJ
-uJ
-uJ
-uJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(153,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-bN
-bN
-gC
-fM
-fM
-dN
-cp
-ft
-iE
-iY
-jv
-aW
-bN
-bt
-aa
-aa
-aa
-bt
-bN
-re
-bN
-bN
-bt
-aa
-aa
-bt
-bN
-fr
-ux
-qi
-qB
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(154,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-fK
-gg
-gw
-fM
-fM
-fM
-hj
-bN
-ih
-iG
-bN
-iF
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ik
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-iF
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-vD
-uJ
-vB
-uJ
-vl
-uJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(155,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-fq
-fJ
-fM
-fM
-fM
-fM
-gW
-hi
-bN
-bN
-iF
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-rg
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-rL
-uJ
-vc
-uJ
-uJ
-uJ
-uJ
-vB
-uJ
-ws
-uJ
-uJ
-uJ
-ra
-sb
-aa
-aa
-ly
-jt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(156,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-cj
-ft
-fM
-fM
-fM
-fM
-fM
-gX
-hk
-bN
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-rh
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-uJ
-uJ
-uJ
-uJ
-uJ
-uJ
-vB
-qq
-kz
-wI
-uJ
-kz
-gq
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(157,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-bN
-bN
-fs
-fL
-gh
-fM
-fM
-gF
-aW
-gm
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-iS
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-aa
-uJ
-uJ
-uJ
-uJ
-uJ
-vB
-vB
-tS
-uJ
-qS
-wZ
-gv
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(158,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bN
-dO
-er
-bN
-ft
-fN
-gj
-fM
-gF
-aW
-ez
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-rg
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kZ
-aa
-aa
-uJ
-uJ
-vW
-uJ
-kz
-kz
-qq
-wJ
-kz
-kz
-ws
-bt
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(159,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-gk
-dN
-eq
-cp
-eq
-fM
-gi
-gx
-aW
-ez
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-rj
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-uJ
-uJ
-wj
-tT
-qV
-qh
-tS
-kz
-ri
-rq
-bt
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(160,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-gk
-dj
-dQ
-es
-eV
-es
-fP
-gl
-bN
-ez
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-rX
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kp
-aa
-aa
-aa
-gU
-aa
-sr
-bt
-wC
-tS
-tS
-kz
-qK
-xy
-tT
-bt
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(161,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bN
-cL
-di
-dP
-eq
-cp
-fu
-fO
-bN
-bt
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cM
-cM
-kc
-rk
-tb
-cM
-cM
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-gp
-wK
-qZ
-tS
-tS
-xy
-tT
-jo
-bN
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(162,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-cN
-dk
-dR
-et
-bN
-fv
-fQ
-gm
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cM
-jD
-pr
-cS
-lm
-sc
-te
-eU
-sI
-td
-cM
-dV
-qg
-jt
-aa
-ae
-aa
-aa
-aa
-ly
-aa
-aa
-aa
-ae
-bN
-wL
-tT
-tT
-tS
-xy
-tS
-jA
-gz
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(163,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ab
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aI
-aJ
-aJ
-aJ
-aJ
-aJ
-aJ
-aJ
-aJ
-aJ
-aI
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-hJ
-hs
-kH
-kY
-hM
-hM
-qd
-kc
-sV
-th
-uF
-sH
-tc
-ha
-tJ
-pY
-lD
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-ae
-bt
-bN
-bN
-vV
-vY
-xz
-xH
-bN
-gK
-bN
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(164,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aY
-bU
-ck
-cP
-cQ
-aJ
-eu
-eX
-aJ
-aI
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-jU
-km
-ks
-ks
-ks
-ks
-qf
-mE
-iJ
-tx
-uH
-sK
-tf
-tw
-ha
-tX
-lD
-lD
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-ae
-ae
-ae
-bt
-bN
-xc
-xp
-rf
-gf
-xY
-xt
-yq
-bN
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(165,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aY
-bT
-cr
-cO
-dl
-dS
-bV
-eW
-aJ
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-hs
-jw
-jT
-ik
-hM
-hM
-ln
-ps
-cM
-nn
-hM
-tA
-cM
-sJ
-pG
-tv
-gE
-lD
-qg
-lD
-sw
-qH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-iF
-xb
-xo
-xA
-ll
-xX
-xI
-yp
-vP
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(166,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aI
-bb
-bW
-cu
-cR
-bV
-aJ
-ev
-eY
-aJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-cH
-hs
-jb
-jy
-jV
-ik
-hM
-hM
-lq
-pv
-cM
-qp
-rH
-sA
-cM
-sL
-ha
-sK
-lD
-lD
-lD
-lD
-lD
-lD
-qg
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-bt
-vP
-xr
-gf
-xI
-ya
-gd
-xI
-xt
-iF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-wr
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(167,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aY
-br
-bV
-ct
-cQ
-bV
-aJ
-aJ
-aJ
-aI
-aa
-aa
-aa
-aa
-ae
-aa
-ae
-cH
-cM
-iH
-ja
-jx
-ij
-iJ
-hM
-iK
-lo
-cM
-cM
-cM
-st
-cM
-cM
-cM
-tg
-pP
-qg
-lD
-lD
-lD
-qg
-ha
-rM
-sj
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xq
-qx
-xI
-xZ
-gd
-xI
-xt
-iF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lI
-lI
-lI
-lI
-lH
-lH
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(168,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-jt
-cI
-ae
-aa
-aa
-aY
-bw
-bV
-cw
-bV
-bV
-dX
-aY
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-hJ
-hL
-iI
-hM
-ij
-iJ
-iR
-kK
-hs
-hJ
-cH
-aa
-qE
-ro
-rZ
-aa
-go
-pL
-lD
-lD
-lD
-lD
-lD
-ha
-sK
-vo
-fb
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-vP
-xC
-gf
-yb
-xI
-gf
-xq
-bN
-bt
-aa
-aa
-aa
-aa
-kA
-aa
-aa
-aa
-kA
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(169,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-cI
-ad
-cI
-aa
-af
-ad
-cI
-aa
-aa
-aY
-bu
-bX
-cv
-bX
-cQ
-dW
-aY
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-hs
-ii
-hM
-ij
-iJ
-iR
-kn
-kJ
-hJ
-aa
-aa
-aa
-qD
-ro
-rY
-ed
-aa
-ae
-ty
-lD
-pY
-lD
-lD
-qw
-ve
-vn
-cH
-cH
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xB
-xC
-rf
-gf
-gf
-xt
-yC
-bN
-aa
-aa
-aa
-kh
-vm
-sC
-aa
-kh
-vm
-sC
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lK
-lK
-lI
-lI
-lI
-lI
-lI
-lK
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(170,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ad
-aa
-aa
-aa
-aa
-ad
-cI
-aa
-aa
-aa
-aa
-aa
-aI
-aJ
-aJ
-aJ
-cy
-aJ
-aJ
-aJ
-aI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cM
-hL
-hM
-ij
-iJ
-hM
-iK
-ko
-cM
-cH
-aa
-aa
-aa
-qE
-ro
-rZ
-aa
-aa
-aa
-aa
-lD
-lD
-qg
-lD
-qy
-ha
-vp
-vb
-cM
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-xK
-yd
-gf
-gf
-xt
-yE
-iF
-aa
-aa
-aa
-kh
-vm
-sC
-aa
-kh
-vm
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lG
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-mb
-mj
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(171,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aJ
-aZ
-bx
-bZ
-cx
-bZ
-dm
-aY
-aa
-aa
-jt
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-hK
-ij
-iJ
-hM
-jz
-hs
-hJ
-cH
-ae
-aa
-aa
-aa
-qE
-ro
-rZ
-gU
-ae
-aa
-aa
-aa
-lD
-qe
-qg
-ha
-tc
-sK
-vE
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xJ
-yc
-gf
-qx
-xt
-yD
-iF
-aa
-aa
-aa
-kh
-vm
-sC
-aa
-kh
-vm
-zn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lK
-lK
-mi
-lK
-mf
-lK
-lK
-mi
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(172,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-ae
-aa
-aK
-bd
-bC
-cb
-cx
-bC
-do
-aY
-aa
-fa
-aa
-aa
-aa
-aa
-aa
-aa
-cM
-hn
-hM
-ik
-hM
-jd
-jB
-hJ
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-rp
-pm
-lD
-aa
-aa
-ae
-aa
-ed
-fb
-uy
-tc
-sK
-vq
-tc
-vN
-cM
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xM
-yc
-gf
-gf
-yp
-yG
-iF
-aa
-aa
-aa
-kh
-vm
-sC
-aa
-kh
-vm
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-nQ
-mm
-mm
-lA
-mm
-mi
-lK
-mf
-lK
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(173,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aK
-bc
-bB
-bC
-cz
-bC
-dn
-aY
-aa
-aa
-aa
-gU
-aa
-aa
-aa
-aa
-cM
-hm
-hM
-ik
-iK
-eT
-cM
-cH
-aa
-aa
-ae
-aa
-cH
-cM
-lh
-pJ
-lD
-lD
-lD
-aa
-tz
-aa
-aa
-cH
-cM
-uM
-sH
-sH
-sH
-vM
-cM
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xL
-ye
-gf
-gf
-yw
-yF
-bN
-aa
-aa
-aa
-kh
-vm
-sC
-aa
-kh
-vm
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-me
-me
-me
-lI
-mm
-mA
-mZ
-mm
-mA
-nF
-nK
-nP
-nT
-mm
-zO
-mm
-mm
-mm
-lK
-lK
-lK
-lI
-lI
-lI
-lH
-lH
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lG
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(174,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aK
-bf
-bD
-cd
-cz
-bC
-dp
-aJ
-aJ
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cS
-hO
-im
-dM
-dT
-cM
-aa
-aa
-aa
-ae
-cH
-cM
-lh
-pJ
-kC
-lD
-sw
-lD
-lD
-aa
-ly
-aa
-aa
-cM
-cM
-cM
-vj
-vt
-eU
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-xp
-rf
-vF
-vF
-gf
-wd
-gL
-bN
-bt
-aa
-aa
-rm
-aa
-aa
-aa
-rm
-aa
-aa
-kA
-kA
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lW
-lX
-lX
-mr
-lX
-mJ
-mA
-zO
-mm
-mA
-mA
-mA
-mA
-nM
-mm
-mC
-oD
-mM
-mm
-ox
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(175,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-af
-ad
-aa
-ad
-aa
-aa
-aa
-aa
-ae
-aa
-jt
-aa
-aL
-be
-bC
-cc
-cz
-bC
-bC
-dY
-aJ
-ee
-eH
-eS
-fm
-ee
-ee
-cJ
-gZ
-eh
-hq
-il
-hN
-je
-cM
-aa
-aa
-aa
-aa
-cM
-lh
-pJ
-gE
-lD
-lD
-qg
-ha
-ti
-aa
-aa
-aa
-aa
-cM
-uK
-uO
-uO
-uO
-uW
-vX
-cM
-fb
-fb
-fb
-fb
-fb
-fb
-bN
-xt
-xN
-vx
-vG
-vU
-wc
-we
-yS
-yX
-za
-oS
-oS
-wl
-oS
-oS
-oS
-wl
-oS
-oS
-wl
-wp
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lU
-lX
-lX
-mr
-lX
-mA
-mA
-mA
-nt
-mA
-mA
-mA
-mA
-mA
-mB
-mA
-mA
-mA
-mm
-mm
-mm
-mm
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(176,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ad
-aa
-aa
-aa
-ad
-aa
-ad
-aa
-aa
-aa
-aa
-aJ
-bh
-bF
-cc
-cA
-cT
-cT
-ea
-ex
-fc
-fy
-fc
-fc
-fy
-fc
-gN
-hc
-eZ
-hr
-io
-iM
-jh
-hJ
-aa
-aa
-aa
-ae
-fb
-pJ
-qg
-lD
-lD
-gE
-sx
-pJ
-fb
-aa
-aa
-aa
-aa
-fb
-uL
-uO
-uS
-uU
-uZ
-ks
-vO
-wk
-wu
-ks
-wk
-wU
-ks
-xs
-xD
-ll
-vz
-vJ
-wa
-xo
-wf
-bN
-bN
-bN
-zf
-aa
-rJ
-aa
-aa
-aa
-rJ
-aa
-aa
-aa
-tE
-zr
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lY
-lX
-lX
-me
-lI
-mm
-lV
-mA
-nu
-mA
-mA
-mA
-mA
-mA
-mm
-mA
-nw
-mA
-mB
-mA
-nw
-mm
-mm
-lK
-lK
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(177,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ad
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aM
-bg
-bE
-cc
-bC
-bC
-bC
-dZ
-aJ
-ee
-ee
-ee
-ee
-ee
-ee
-cJ
-bS
-hb
-ht
-in
-hP
-jg
-cM
-aa
-aa
-jt
-aa
-fR
-pH
-lD
-ha
-lD
-sa
-pJ
-lh
-cM
-aa
-aa
-aa
-aa
-cM
-uN
-uP
-uT
-uO
-va
-hM
-cM
-fb
-fb
-fb
-fb
-fb
-fb
-bN
-xq
-xO
-yw
-vK
-wb
-xo
-wg
-yU
-yZ
-zc
-oS
-oS
-wm
-oS
-oS
-oS
-wm
-oS
-oS
-wm
-wq
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lG
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lX
-lX
-lX
-me
-lI
-mm
-mA
-mA
-mA
-mA
-mA
-ni
-mA
-nM
-mm
-os
-mA
-ni
-mm
-mA
-mA
-nx
-mm
-ox
-mb
-pd
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(178,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-ae
-aa
-aa
-aP
-bk
-bH
-ce
-bC
-bC
-dr
-aJ
-aJ
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cM
-hR
-iq
-cM
-cM
-cM
-aa
-aa
-aa
-kZ
-lD
-lD
-lD
-pJ
-lb
-pJ
-lh
-cM
-cH
-aa
-aa
-aa
-aa
-cM
-cM
-cM
-vr
-vA
-cM
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-xr
-gf
-vT
-vT
-gf
-wi
-gL
-bN
-bt
-aa
-aa
-rm
-aa
-aa
-aa
-rm
-aa
-aa
-ky
-ky
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lJ
-lX
-lX
-lX
-me
-lI
-mm
-mZ
-zO
-mm
-mm
-mm
-mm
-mB
-mm
-mm
-mm
-mB
-oO
-mm
-mm
-lV
-pz
-mm
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(179,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-cI
-aa
-aa
-aa
-aN
-bi
-bG
-bC
-bC
-bC
-dq
-aY
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cM
-ho
-hQ
-ip
-iN
-ji
-dV
-cH
-aa
-gU
-aa
-ly
-pK
-gn
-hp
-rr
-lh
-cM
-cH
-aa
-aa
-aa
-aa
-cH
-cM
-tl
-sO
-vs
-sO
-vQ
-cM
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xP
-xr
-gf
-gf
-yw
-yL
-bN
-aa
-aa
-aa
-kh
-wo
-sC
-aa
-kh
-wo
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lI
-lH
-lH
-lJ
-lX
-lX
-lX
-me
-lI
-mm
-mm
-mB
-mm
-mm
-mM
-mA
-mA
-nU
-of
-ot
-mA
-mA
-pb
-pi
-mA
-py
-mm
-lK
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(180,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-cI
-aa
-aa
-aa
-aa
-aa
-aK
-bm
-bJ
-bC
-bC
-cV
-dt
-aY
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cM
-hv
-hT
-is
-hM
-hM
-jH
-hJ
-kp
-aa
-aa
-ed
-aa
-go
-cM
-ru
-cM
-cH
-aa
-ae
-ae
-ae
-aa
-hJ
-tl
-uQ
-sO
-vs
-sO
-vR
-cM
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xR
-xq
-gf
-gf
-yx
-yO
-iF
-aa
-aa
-aa
-kh
-wo
-sC
-aa
-kh
-wo
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lH
-lI
-ma
-lX
-mk
-me
-lI
-mm
-nd
-mA
-mA
-mm
-mR
-mA
-mA
-mB
-mA
-mA
-mA
-mA
-nX
-mm
-mA
-mA
-mm
-lK
-lK
-lK
-mf
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(181,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aJ
-bl
-bI
-cf
-bC
-cU
-ds
-aY
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cY
-hS
-ir
-iP
-hM
-jG
-jj
-hJ
-cH
-aa
-ae
-gU
-aa
-qE
-rt
-rZ
-ae
-ae
-ae
-ae
-cH
-hJ
-cH
-sO
-sO
-tZ
-vs
-sM
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xQ
-xt
-gf
-gf
-xt
-yN
-iF
-aa
-aa
-aa
-kh
-wo
-sC
-aa
-kg
-zm
-zo
-aa
-ab
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lZ
-lY
-lX
-me
-lI
-mK
-nd
-nd
-mA
-mm
-nx
-mA
-nw
-mm
-lV
-mA
-mA
-mA
-pc
-mm
-mm
-mB
-mm
-mm
-lK
-lK
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(182,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-af
-aa
-aa
-ae
-aa
-aa
-aI
-aJ
-aJ
-aJ
-cB
-aJ
-aJ
-aJ
-aI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-cM
-hV
-hM
-ir
-iP
-hM
-ka
-kr
-ep
-cH
-ae
-aa
-jt
-qD
-rt
-rY
-aa
-aa
-aa
-cH
-cM
-tY
-sO
-sO
-sO
-vg
-vv
-vI
-cM
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-bN
-xK
-xp
-gf
-gf
-xt
-yQ
-iF
-aa
-aa
-ae
-kh
-wo
-sC
-aa
-zl
-zl
-zl
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lU
-lU
-ml
-me
-lI
-mm
-nf
-nd
-nd
-mm
-mm
-mB
-mm
-mm
-mt
-mA
-nW
-oQ
-mA
-mB
-mA
-mA
-pE
-mm
-lA
-mm
-ox
-lK
-lI
-lI
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(183,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cI
-aa
-aa
-aa
-cI
-ad
-aa
-aa
-aa
-aY
-bK
-bZ
-cg
-bZ
-du
-ec
-aJ
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-cH
-hU
-it
-hM
-ir
-iP
-iR
-kq
-kL
-hJ
-aa
-aa
-aa
-qE
-rt
-rZ
-aa
-aa
-aa
-hJ
-tL
-tl
-sO
-sO
-uR
-vf
-vu
-vi
-cH
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-rQ
-xp
-gf
-gf
-gf
-xt
-yP
-bN
-aa
-aa
-aa
-kh
-wo
-sC
-aa
-zk
-zl
-zl
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-me
-me
-me
-lI
-mm
-mc
-nf
-mm
-mm
-mS
-mA
-nM
-mm
-og
-mA
-mA
-oh
-ou
-oy
-oH
-ou
-ou
-oy
-zS
-oy
-pe
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lG
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(184,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cI
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cI
-aa
-aa
-aa
-aY
-bM
-cg
-cD
-cD
-cD
-ef
-aJ
-aI
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-hw
-hW
-iu
-iR
-hM
-jI
-iP
-hM
-kN
-hU
-hJ
-cH
-aa
-qE
-rt
-rZ
-aa
-cH
-hJ
-cH
-tl
-sO
-tk
-un
-up
-uA
-vw
-hJ
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-bt
-vP
-xp
-gf
-gf
-gf
-gf
-yz
-bN
-bt
-aa
-aa
-aa
-aa
-ky
-aa
-aa
-aa
-zl
-ae
-aa
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-mm
-mA
-nf
-mm
-nz
-mA
-mA
-mA
-nV
-ny
-ov
-nL
-oi
-ow
-mm
-mm
-mB
-mm
-mm
-mC
-mm
-mm
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(185,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aY
-bL
-cg
-cC
-cW
-dv
-cg
-eA
-aJ
-aI
-aa
-aa
-aa
-aa
-ae
-ae
-ae
-cH
-hU
-iQ
-jk
-iJ
-ik
-hM
-hM
-la
-lM
-cM
-cM
-cM
-rv
-cM
-cM
-cM
-tk
-sO
-sO
-tZ
-un
-up
-uA
-vh
-cM
-cH
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-iF
-xt
-gf
-gf
-gf
-gf
-ge
-yy
-iF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-mb
-lK
-lI
-lI
-lI
-mm
-zP
-mA
-mB
-mA
-mA
-mA
-mA
-mm
-nr
-nB
-oE
-oR
-oE
-oz
-pb
-mA
-mA
-mm
-mA
-pI
-mm
-ox
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(186,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aI
-aJ
-ci
-cF
-cX
-dw
-cg
-cg
-fe
-aY
-aa
-aa
-aa
-ae
-ae
-ae
-ae
-ae
-cH
-cM
-cM
-iV
-kb
-ks
-ks
-iP
-hM
-pM
-cM
-qN
-rW
-sW
-cM
-sN
-tl
-sO
-sO
-ub
-up
-uA
-uA
-cH
-cH
-ae
-ae
-aa
-ae
-ae
-aa
-aa
-aa
-bt
-vP
-xp
-gf
-gf
-gf
-gf
-qx
-yB
-iF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lp
-lK
-lI
-lI
-lI
-mm
-mm
-mB
-mm
-mm
-mm
-mB
-mm
-mm
-mm
-nD
-oc
-oU
-pf
-nD
-nX
-mA
-mA
-mB
-mA
-mA
-mm
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(187,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-al
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aY
-ch
-cE
-cE
-cE
-cg
-cg
-fd
-aY
-ae
-ae
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-cH
-dU
-jJ
-hM
-hM
-hM
-ik
-hM
-jG
-cM
-pj
-ik
-tK
-cM
-sM
-sO
-tk
-tM
-ua
-uo
-uz
-cH
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-iF
-xe
-xo
-gf
-gf
-gf
-gf
-yt
-vP
-bt
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lI
-lH
-lI
-lI
-lK
-mf
-mm
-mm
-mm
-mm
-mm
-mA
-nv
-nx
-mm
-mA
-mA
-nW
-mA
-nC
-oG
-oT
-mA
-oA
-nX
-mA
-mA
-mm
-mm
-mB
-mm
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(188,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fZ
-aa
-aa
-aa
-aa
-aa
-af
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aY
-bY
-cG
-cZ
-dx
-cf
-eB
-ff
-aJ
-aI
-ae
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-hU
-fA
-kt
-kP
-ld
-ks
-ks
-qk
-pT
-rw
-tP
-sz
-sP
-tm
-tm
-tO
-ud
-uq
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-bt
-bN
-xg
-xv
-qx
-gf
-yh
-yo
-yu
-bN
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lG
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lK
-lK
-mm
-ms
-mA
-mM
-mm
-mA
-mA
-nx
-nI
-mA
-mA
-nY
-oj
-nG
-oJ
-oW
-oj
-nG
-oI
-pA
-mA
-mB
-mA
-nw
-mm
-lK
-lK
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(189,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-bz
-bz
-bz
-bz
-bz
-bz
-bz
-bn
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-hJ
-hU
-kO
-lc
-hM
-hM
-qj
-qC
-ik
-tW
-sy
-sO
-sO
-tl
-tN
-uV
-hJ
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-bn
-bz
-bz
-bz
-bz
-xF
-xS
-bz
-bz
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-mg
-mm
-ms
-mA
-mM
-mm
-mA
-mA
-mA
-mm
-mA
-mA
-nX
-nX
-nE
-od
-oV
-mA
-nC
-mA
-nW
-mA
-mm
-mS
-mA
-mm
-lK
-mf
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(190,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-gU
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-da
-dz
-eg
-bz
-fh
-fB
-fT
-gr
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cM
-lN
-pN
-cM
-qI
-sY
-uc
-cM
-hu
-tn
-cM
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-bz
-wN
-wW
-xh
-gt
-jC
-jm
-rG
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lI
-lH
-lH
-lI
-lI
-lI
-lI
-lK
-lK
-mm
-ms
-mA
-mN
-mm
-mw
-mA
-mA
-mm
-DH
-mA
-nZ
-ol
-nD
-oK
-oV
-mA
-nD
-pt
-mA
-mA
-mm
-nx
-mA
-mm
-mm
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(191,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bz
-da
-dy
-dy
-eC
-fg
-fl
-fS
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-cM
-cM
-qJ
-ik
-um
-cM
-cM
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-wM
-wV
-wQ
-gt
-fl
-jm
-rG
-bz
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-lK
-mm
-mt
-mA
-mA
-mm
-mA
-nw
-mA
-mB
-mA
-mA
-nZ
-ok
-nH
-oE
-oX
-pg
-oC
-mm
-mB
-mm
-mm
-nx
-mA
-os
-mm
-lK
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(192,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-dA
-dA
-bz
-fj
-fl
-fU
-bz
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-cH
-cM
-rx
-cM
-cH
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-wE
-wP
-wV
-wQ
-fl
-fl
-rD
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-lK
-mm
-mv
-mA
-mA
-mm
-mA
-mA
-mA
-mm
-mA
-mA
-mA
-mA
-mB
-mA
-oU
-mA
-nX
-mm
-mA
-nM
-mm
-mm
-mB
-mm
-mm
-ox
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(193,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ed
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-bz
-fi
-fl
-fl
-gs
-fl
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ik
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-wv
-su
-wO
-wX
-xi
-fl
-xG
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lI
-lI
-lK
-lK
-mm
-mu
-mA
-mA
-mB
-mA
-nx
-nx
-mm
-mA
-nR
-oa
-om
-mm
-mA
-oY
-mA
-nX
-mm
-lV
-mA
-nx
-nx
-mA
-mA
-mm
-lK
-lK
-lI
-lI
-lI
-lH
-lI
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(194,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bz
-bn
-bO
-fl
-fl
-fl
-gs
-fl
-fl
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ry
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-fI
-wn
-wv
-sB
-qb
-fl
-fl
-fl
-xG
-cq
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lI
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-lK
-mm
-mm
-mB
-mm
-mm
-mB
-mm
-mm
-mm
-mB
-mm
-mm
-oo
-mm
-lV
-mA
-mA
-mA
-mB
-mA
-mA
-mA
-mA
-mA
-mA
-mm
-lK
-lK
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(195,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-ca
-fk
-fk
-fV
-bz
-fl
-gt
-gP
-bz
-gr
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ik
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-gr
-bz
-bz
-sk
-ss
-sQ
-wQ
-fl
-fl
-qR
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lK
-mg
-mm
-mR
-mA
-mB
-mA
-mA
-mA
-mC
-mA
-mA
-zP
-mm
-zR
-oo
-oL
-ns
-mA
-pn
-mm
-nf
-mA
-mA
-nw
-mA
-nM
-mm
-lK
-lK
-lI
-lI
-lH
-lI
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(196,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-bz
-bz
-bz
-fl
-fl
-gR
-bz
-hy
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ik
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-vS
-vZ
-bz
-jl
-lv
-pB
-fl
-fl
-wH
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lH
-lI
-lI
-lI
-lK
-lK
-lK
-mm
-mM
-mA
-mO
-mh
-mA
-mA
-mm
-mA
-mA
-mt
-mm
-oq
-mm
-mm
-mm
-mm
-mm
-mm
-mB
-mK
-mm
-mm
-mm
-mm
-mm
-ox
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(197,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-cq
-fW
-gt
-fl
-fl
-gQ
-bz
-hx
-hA
-bn
-gr
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-ry
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-gr
-bn
-ug
-ug
-ug
-wh
-jm
-jm
-fl
-fl
-fl
-cq
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lK
-mf
-mm
-mm
-mC
-mm
-nk
-ns
-mA
-nA
-lV
-mA
-nS
-mm
-op
-oB
-oM
-oZ
-ob
-mA
-pu
-mA
-mA
-mM
-mm
-lK
-lK
-lK
-mf
-lK
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(198,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-fW
-fl
-fl
-fl
-gQ
-he
-hA
-eF
-hA
-iT
-bz
-gr
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-fb
-rh
-fb
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-gr
-vd
-ug
-ug
-ug
-ug
-ug
-wh
-ic
-fl
-fl
-fl
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lG
-lH
-lI
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-lK
-mn
-lA
-zO
-mm
-no
-mA
-zP
-mm
-zP
-mA
-mA
-ob
-or
-nJ
-oe
-pa
-mm
-nM
-mA
-mA
-mA
-mM
-mm
-lK
-lK
-lK
-ph
-lK
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lG
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(199,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-gu
-fl
-gt
-gS
-bz
-hz
-hY
-iv
-hA
-jn
-jL
-bz
-bz
-bn
-aa
-aa
-aa
-bn
-bz
-rz
-bz
-bn
-aa
-aa
-aa
-bn
-bz
-bz
-uB
-jc
-jR
-jZ
-jR
-kM
-vH
-bz
-jC
-gt
-wH
-bn
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lK
-lK
-lK
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-OV
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-mm
-ox
-lK
-mb
-lK
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(200,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-gA
-gG
-bz
-bz
-hC
-hA
-ix
-gD
-jp
-jM
-hA
-ku
-bz
-bz
-ew
-bz
-bz
-qo
-rB
-sd
-bz
-bz
-bz
-bz
-bz
-uf
-us
-ug
-jQ
-fl
-fl
-fl
-fl
-kB
-bz
-kE
-lR
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lK
-lK
-lK
-mf
-lK
-mn
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-mf
-mn
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lH
-lI
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(201,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-bz
-ey
-hB
-ia
-iw
-ia
-ia
-ia
-hB
-ia
-kQ
-le
-lQ
-pO
-qm
-qm
-rA
-qo
-qo
-sR
-to
-tB
-bz
-ue
-ur
-ug
-jQ
-fl
-fl
-kB
-fl
-lr
-bz
-cq
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lI
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lK
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(202,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-hf
-hg
-hA
-hA
-hY
-jr
-iU
-iU
-iU
-kR
-lg
-hF
-gy
-qo
-qo
-rC
-qo
-qo
-lS
-tp
-lg
-tQ
-ug
-ug
-ut
-jQ
-fl
-fl
-fl
-fl
-ls
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-OX
-KK
-OX
-OX
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(203,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-ib
-iy
-gM
-jq
-jq
-kd
-kv
-eD
-lf
-lf
-lg
-qn
-lf
-rC
-jE
-lf
-lf
-lf
-lg
-bz
-ug
-ut
-ug
-jc
-jW
-jW
-jW
-kU
-vL
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-Hg
-lX
-lX
-OX
-lI
-lI
-lI
-lI
-OX
-OX
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lK
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(204,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bn
-iz
-ig
-js
-gO
-kf
-gO
-kS
-lg
-lf
-hI
-hA
-qL
-sZ
-se
-hA
-lf
-lf
-lf
-tQ
-ug
-ug
-ug
-uX
-vk
-vy
-vd
-bz
-fC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-Yh
-lX
-lX
-OX
-OX
-yg
-lK
-UB
-lK
-lK
-lI
-lI
-lI
-OX
-OX
-lK
-lK
-lK
-lK
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(205,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-gr
-gr
-bz
-jN
-ke
-kw
-bz
-jX
-lT
-pQ
-hA
-hA
-rE
-hY
-hA
-sS
-tq
-tC
-bz
-uh
-uu
-uC
-bz
-gr
-gr
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lI
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-Pn
-lX
-lX
-Mc
-ZQ
-BB
-lK
-YV
-Sv
-OX
-OX
-lI
-lI
-lI
-lK
-lI
-lK
-OX
-OX
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(206,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-bz
-bz
-bz
-li
-md
-pR
-on
-rl
-sg
-sX
-uD
-sT
-tp
-tD
-bz
-bz
-bz
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-GF
-lX
-UM
-OX
-OX
-lI
-Sv
-lK
-lK
-lI
-lK
-lK
-lK
-lK
-lK
-lH
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(207,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-bz
-gr
-gr
-bz
-qM
-eG
-sf
-bz
-gr
-gr
-bz
-bn
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-OX
-GH
-OX
-OX
-lI
-lI
-lK
-lK
-lI
-lI
-lK
-OX
-lI
-lK
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(208,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bz
-qP
-bz
-si
-bz
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-OX
-OX
-lI
-lI
-lI
-lI
-lK
-lK
-lK
-lK
-OX
-lK
-lK
-OX
-lK
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lG
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(209,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-bn
-qO
-bz
-sv
-bn
-ae
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lK
-lK
-lK
-lK
-lK
-lI
-OX
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(210,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-rm
-rI
-rm
-aa
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lG
-lH
-lH
-lI
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-OX
-OX
-lH
-lK
-lK
-lK
-OX
-lI
-lK
-lK
-lK
-lK
-lK
-lK
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(211,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kx
-kx
-kx
-kx
-kx
-aa
-rm
-aa
-rm
-ae
-kA
-kx
-kA
-kA
-kA
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lI
-lH
-lH
-OX
-lK
-lI
-OX
-lK
-lI
-lI
-lI
-lK
-lK
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(212,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kg
-jK
-jK
-jK
-jK
-jK
-oS
-rn
-rJ
-tE
-oS
-uI
-uI
-uI
-uI
-uI
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lI
-lI
-lH
-lH
-lI
-lI
-lI
-lI
-lH
-lI
-lI
-lI
-lI
-lH
-lH
-lH
-lH
-lI
-OX
-lK
-lI
-lK
-lK
-lK
-lK
-lK
-lK
-OX
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(213,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ky
-ky
-ky
-ky
-ky
-aa
-rm
-aa
-rm
-aa
-ky
-ky
-ky
-ky
-ky
-ae
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lI
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lK
-lK
-lI
-lI
-lI
-OX
-OX
-lI
-lH
-OX
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(214,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-rm
-aa
-rm
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lK
-lH
-lH
-lI
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(215,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kA
-kA
-kA
-kA
-kA
-aa
-rm
-aa
-rm
-aa
-kA
-kA
-kA
-kA
-kA
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(216,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kh
-jK
-jK
-jK
-jK
-jK
-oS
-rn
-rJ
-tE
-oS
-uI
-uI
-uI
-uI
-uI
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(217,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ky
-ky
-ky
-ky
-ky
-aa
-rm
-aa
-rm
-aa
-ky
-ky
-ky
-ky
-ky
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lH
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(218,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-rm
-aa
-rm
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lG
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-lF
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(219,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kh
-rn
-aa
-tE
-kg
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(220,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-kh
-rF
-sh
-tH
-sC
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(221,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-ky
-rK
-ky
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(222,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(223,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(224,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(225,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(226,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(227,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(228,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(229,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(230,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(231,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(232,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(233,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(234,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(235,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(236,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(237,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(238,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(239,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(240,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(241,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(242,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(243,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(244,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(245,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(246,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(247,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(248,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(249,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(250,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(251,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(252,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(253,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(254,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
-(255,1,1) = {"
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-aa
-"}
diff --git a/_maps/map_files/generic/Lavaland.dmm b/_maps/map_files/generic/Lavaland.dmm
index 142bbcff5f7..e44b9f52458 100644
--- a/_maps/map_files/generic/Lavaland.dmm
+++ b/_maps/map_files/generic/Lavaland.dmm
@@ -924,6 +924,7 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/production)
"cn" = (
@@ -1008,6 +1009,11 @@
/obj/effect/turf_decal/tile/brown{
dir = 2
},
+/obj/machinery/camera{
+ c_tag = "Shuttle Docking Foyer North";
+ dir = 8;
+ network = list("Mining Outpost")
+ },
/turf/simulated/floor/plasteel,
/area/mine/production)
"cx" = (
@@ -1324,10 +1330,10 @@
/turf/simulated/floor/plasteel/dark,
/area/mine/maintenance)
"di" = (
-/obj/machinery/telecomms/relay/preset/mining,
/obj/machinery/light/small{
dir = 1
},
+/obj/machinery/tcomms/relay/mining,
/turf/simulated/floor/plasteel/dark,
/area/mine/maintenance)
"dj" = (
@@ -1428,11 +1434,6 @@
/obj/machinery/light{
dir = 4
},
-/obj/machinery/camera{
- c_tag = "Shuttle Docking Foyer";
- dir = 8;
- network = list("Mining Outpost")
- },
/obj/machinery/newscaster{
pixel_x = 30;
pixel_y = 1
@@ -1443,6 +1444,11 @@
/obj/effect/turf_decal/tile/brown{
dir = 2
},
+/obj/machinery/camera{
+ c_tag = "Shuttle Docking Foyer South";
+ dir = 8;
+ network = list("Mining Outpost")
+ },
/turf/simulated/floor/plasteel,
/area/mine/production)
"dw" = (
@@ -1897,6 +1903,7 @@
/obj/structure/cable{
icon_state = "1-4"
},
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/living_quarters)
"eu" = (
@@ -2019,6 +2026,7 @@
/obj/structure/cable{
icon_state = "2-8"
},
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/production)
"eD" = (
@@ -2396,6 +2404,7 @@
/obj/effect/turf_decal/tile/purple{
dir = 1
},
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/living_quarters)
"fv" = (
@@ -2794,6 +2803,7 @@
dir = 1
},
/obj/effect/turf_decal/tile/bar,
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/living_quarters)
"gj" = (
@@ -3056,6 +3066,7 @@
dir = 6
},
/obj/effect/baseturf_helper/lava_land/surface,
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel/dark,
/area/mine/maintenance)
"gJ" = (
@@ -4119,6 +4130,7 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
+/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/mine/production)
"BD" = (
@@ -4266,6 +4278,10 @@
},
/turf/simulated/floor/plasteel,
/area/mine/production)
+"Ww" = (
+/obj/machinery/hologram/holopad,
+/turf/simulated/floor/plasteel,
+/area/mine/eva)
"WO" = (
/obj/effect/spawner/window,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
@@ -20693,7 +20709,7 @@ ab
bg
bs
bY
-bY
+Ww
bU
cp
bf
diff --git a/_maps/map_files/generic/z6.dmm b/_maps/map_files/generic/space.dmm
similarity index 100%
rename from _maps/map_files/generic/z6.dmm
rename to _maps/map_files/generic/space.dmm
diff --git a/_maps/map_files/generic/z7.dmm b/_maps/map_files/generic/z7.dmm
deleted file mode 100644
index 75f69ec7fe6..00000000000
--- a/_maps/map_files/generic/z7.dmm
+++ /dev/null
@@ -1,65540 +0,0 @@
-//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
-"a" = (
-/turf/space,
-/area/space)
-
-(1,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(2,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(3,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(4,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(5,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(6,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(7,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(8,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(9,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(10,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(11,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(12,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(13,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(14,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(15,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(16,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(17,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(18,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(19,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(20,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(21,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(22,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(23,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(24,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(25,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(26,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(27,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(28,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(29,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(30,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(31,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(32,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(33,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(34,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(35,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(36,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(37,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(38,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(39,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(40,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(41,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(42,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(43,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(44,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(45,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(46,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(47,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(48,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(49,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(50,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(51,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(52,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(53,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(54,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(55,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(56,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(57,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(58,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(59,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(60,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(61,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(62,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(63,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(64,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(65,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(66,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(67,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(68,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(69,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(70,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(71,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(72,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(73,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(74,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(75,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(76,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(77,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(78,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(79,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(80,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(81,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(82,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(83,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(84,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(85,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(86,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(87,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(88,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(89,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(90,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(91,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(92,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(93,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(94,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(95,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(96,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(97,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(98,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(99,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(100,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(101,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(102,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(103,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(104,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(105,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(106,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(107,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(108,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(109,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(110,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(111,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(112,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(113,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(114,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(115,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(116,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(117,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(118,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(119,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(120,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(121,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(122,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(123,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(124,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(125,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(126,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(127,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(128,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(129,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(130,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(131,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(132,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(133,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(134,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(135,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(136,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(137,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(138,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(139,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(140,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(141,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(142,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(143,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(144,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(145,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(146,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(147,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(148,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(149,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(150,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(151,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(152,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(153,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(154,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(155,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(156,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(157,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(158,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(159,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(160,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(161,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(162,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(163,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(164,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(165,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(166,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(167,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(168,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(169,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(170,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(171,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(172,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(173,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(174,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(175,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(176,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(177,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(178,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(179,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(180,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(181,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(182,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(183,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(184,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(185,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(186,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(187,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(188,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(189,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(190,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(191,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(192,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(193,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(194,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(195,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(196,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(197,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(198,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(199,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(200,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(201,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(202,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(203,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(204,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(205,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(206,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(207,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(208,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(209,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(210,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(211,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(212,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(213,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(214,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(215,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(216,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(217,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(218,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(219,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(220,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(221,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(222,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(223,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(224,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(225,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(226,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(227,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(228,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(229,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(230,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(231,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(232,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(233,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(234,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(235,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(236,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(237,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(238,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(239,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(240,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(241,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(242,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(243,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(244,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(245,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(246,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(247,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(248,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(249,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(250,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(251,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(252,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(253,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(254,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
-(255,1,1) = {"
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-a
-"}
diff --git a/_maps/map_files/shuttles/emergency_cyb.dmm b/_maps/map_files/shuttles/emergency_cyb.dmm
index 995f5af74d2..baccd222187 100644
--- a/_maps/map_files/shuttles/emergency_cyb.dmm
+++ b/_maps/map_files/shuttles/emergency_cyb.dmm
@@ -17,72 +17,100 @@
"ad" = (
/turf/space,
/turf/simulated/shuttle/wall{
- tag = "icon-swall_f10";
icon_state = "swall_f10";
dir = 2
},
/area/shuttle/escape)
"ae" = (
-/turf/simulated/shuttle/wall{
- icon_state = "swallc4"
+/obj/structure/table/reinforced,
+/obj/item/paper_bin,
+/obj/item/pen,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "vault"
},
/area/shuttle/escape)
"af" = (
-/obj/machinery/computer/emergency_shuttle,
-/turf/simulated/shuttle/floor,
+/obj/structure/table/reinforced,
+/obj/item/folder/red,
+/obj/item/restraints/handcuffs,
+/obj/item/flash,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
/area/shuttle/escape)
"ag" = (
-/turf/simulated/shuttle/wall{
- icon_state = "swallc3"
+/obj/machinery/computer/robotics,
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkblue"
},
/area/shuttle/escape)
"ah" = (
-/obj/machinery/computer/security{
- network = list("SS13","Telecomms","Research Outpost","Mining Outpost")
+/obj/machinery/computer/crew,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
},
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"ai" = (
-/obj/structure/chair/comfy/shuttle{
- dir = 1
+/obj/machinery/computer/emergency_shuttle,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "darkblue"
},
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"aj" = (
/obj/machinery/computer/communications,
-/turf/simulated/shuttle/floor,
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkblue"
+ },
/area/shuttle/escape)
"ak" = (
-/obj/machinery/computer/station_alert,
-/turf/simulated/shuttle/floor,
+/obj/structure/table/reinforced,
+/obj/item/storage/fancy/donut_box,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/shuttle/escape)
+"al" = (
+/obj/structure/table/reinforced,
+/obj/machinery/cell_charger,
+/obj/item/stock_parts/cell/high,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "vault"
+ },
/area/shuttle/escape)
"am" = (
-/turf/simulated/shuttle/floor,
+/obj/structure/table/reinforced,
+/obj/machinery/recharger,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "vault"
+ },
/area/shuttle/escape)
"an" = (
-/obj/machinery/computer/crew,
-/obj/machinery/status_display{
- pixel_y = 30
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
},
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"ao" = (
-/obj/structure/closet/walllocker/emerglocker{
- pixel_x = -28
- },
/obj/structure/chair/comfy/shuttle{
dir = 1
},
-/turf/simulated/shuttle/floor,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
/area/shuttle/escape)
"ap" = (
-/obj/structure/closet/walllocker/emerglocker{
- pixel_x = 28
+/obj/structure/table/reinforced,
+/obj/item/storage/toolbox/mechanical,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "vault"
},
-/obj/structure/chair/comfy/shuttle{
- dir = 1
- },
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"aq" = (
/turf/simulated/shuttle/wall{
@@ -91,24 +119,44 @@
},
/area/shuttle/escape)
"ar" = (
-/obj/machinery/computer/robotics,
-/turf/simulated/shuttle/floor,
+/obj/machinery/computer/security{
+ network = list("SS13","Research Outpost","Mining Outpost","Telecomms")
+ },
+/obj/structure/sign/poster/official/nanotrasen_logo{
+ pixel_x = -32;
+ pixel_y = 0
+ },
+/turf/simulated/floor/plasteel{
+ dir = 9;
+ icon_state = "darkred"
+ },
/area/shuttle/escape)
"as" = (
/obj/structure/chair/comfy/shuttle{
dir = 8
},
-/turf/simulated/shuttle/floor,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
/area/shuttle/escape)
"at" = (
-/obj/machinery/light/spot,
-/turf/simulated/shuttle/floor,
+/obj/item/radio/intercom{
+ dir = 4;
+ name = "Station Intercom (General)";
+ pixel_x = 29;
+ pixel_y = -60
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
/area/shuttle/escape)
"au" = (
/obj/structure/chair/comfy/shuttle{
dir = 4
},
-/turf/simulated/shuttle/floor,
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
/area/shuttle/escape)
"av" = (
/turf/simulated/shuttle/wall{
@@ -123,16 +171,21 @@
},
/area/shuttle/escape)
"ax" = (
-/obj/machinery/door/airlock/command/glass{
- name = "Escape Shuttle Cockpit";
- req_access_txt = "19"
+/obj/machinery/computer/station_alert,
+/obj/structure/sign/poster/official/nanotrasen_logo{
+ pixel_x = 32;
+ pixel_y = 0
+ },
+/turf/simulated/floor/plasteel{
+ dir = 5;
+ icon_state = "darkyellow"
},
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"ay" = (
-/turf/simulated/shuttle/wall{
- icon_state = "swall14";
- dir = 2
+/obj/machinery/computer/secure_data,
+/turf/simulated/floor/plasteel{
+ dir = 10;
+ icon_state = "darkred"
},
/area/shuttle/escape)
"az" = (
@@ -142,42 +195,35 @@
/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aA" = (
-/obj/machinery/status_display{
- pixel_y = 30
- },
-/obj/machinery/light/spot{
- tag = "icon-tube1 (NORTH)";
- icon_state = "tube1";
- dir = 1
- },
-/obj/structure/chair/comfy/shuttle,
-/turf/simulated/shuttle/floor4,
-/area/shuttle/escape)
-"aB" = (
-/obj/machinery/door/airlock/shuttle{
- aiControlDisabled = 1;
- hackProof = 1;
- id_tag = "s_docking_airlock";
- name = "Shuttle Hatch"
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
- },
-/area/shuttle/escape)
-"aC" = (
-/obj/structure/chair/comfy/shuttle{
- dir = 4
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
-/area/shuttle/escape)
-"aD" = (
+/obj/machinery/light,
/obj/structure/chair/comfy/shuttle{
dir = 8
},
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/shuttle/escape)
+"aB" = (
+/obj/machinery/light,
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "dark"
+ },
+/area/shuttle/escape)
+"aC" = (
+/obj/machinery/computer/atmos_alert,
+/turf/simulated/floor/plasteel{
+ dir = 6;
+ icon_state = "darkyellow"
+ },
+/area/shuttle/escape)
+"aD" = (
+/obj/machinery/status_display,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall12";
+ dir = 2
},
/area/shuttle/escape)
"aE" = (
@@ -188,39 +234,31 @@
/turf/simulated/floor/plating,
/area/shuttle/escape)
"aF" = (
-/obj/machinery/status_display{
- pixel_y = 30
+/obj/machinery/door/airlock/command/glass{
+ name = "Escape Shuttle Cockpit";
+ req_access_txt = "19"
},
-/obj/machinery/light/spot{
- tag = "icon-tube1 (NORTH)";
- icon_state = "tube1";
- dir = 1
- },
-/turf/simulated/shuttle/floor,
+/turf/simulated/floor/plasteel,
/area/shuttle/escape)
"aG" = (
-/obj/structure/closet/walllocker/emerglocker{
- pixel_x = -28
- },
-/obj/structure/chair/comfy/shuttle{
- dir = 4
- },
+/obj/structure/table/reinforced,
/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aH" = (
/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aI" = (
-/obj/machinery/door/airlock/security/glass{
- name = "Escape Shuttle Cell";
- req_access_txt = "2"
+/obj/machinery/light{
+ dir = 1;
+ on = 1
},
-/turf/simulated/floor/plating,
+/obj/structure/chair/comfy/shuttle,
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aJ" = (
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
+/obj/structure/table/reinforced,
+/obj/item/storage/fancy/donut_box,
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aK" = (
/obj/structure/grille,
@@ -230,24 +268,22 @@
/turf/simulated/floor/plating,
/area/shuttle/escape)
"aL" = (
-/obj/structure/closet/walllocker/emerglocker{
- pixel_x = 28
+/obj/structure/table/reinforced,
+/obj/item/storage/firstaid/regular,
+/obj/machinery/light{
+ dir = 1;
+ on = 1
},
-/obj/structure/chair/comfy/shuttle{
- dir = 8
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "redcorner"
},
/area/shuttle/escape)
"aM" = (
-/obj/machinery/door/airlock/shuttle{
- aiControlDisabled = 1;
- hackProof = 1;
- id_tag = "s_docking_airlock";
- name = "Shuttle Hatch"
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "blue"
},
-/turf/simulated/floor/plating,
/area/shuttle/escape)
"aN" = (
/obj/structure/chair/comfy/shuttle{
@@ -274,105 +310,81 @@
/turf/simulated/floor/plating,
/area/shuttle/escape)
"aR" = (
-/obj/docking_port/mobile/emergency{
+/obj/structure/closet/fireaxecabinet{
+ pixel_x = 32;
+ pixel_y = 0
+ },
+/obj/machinery/light{
+ dir = 1;
+ on = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/simulated/floor/plasteel{
dir = 4;
- dwidth = 11;
- height = 13;
- timid = 1;
- width = 24
+ icon_state = "neutralcorner"
},
-/obj/machinery/door/airlock/shuttle{
- aiControlDisabled = 1;
- hackProof = 1;
- id_tag = "s_docking_airlock";
- name = "Shuttle Hatch"
- },
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"aS" = (
+/obj/item/storage/firstaid/o2,
+/obj/structure/table,
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"aT" = (
+/obj/machinery/light{
+ dir = 1;
+ on = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"aU" = (
+/obj/structure/chair/comfy/shuttle,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"aV" = (
+/obj/structure/closet/crate/internals,
+/obj/item/clothing/mask/breath,
+/obj/item/clothing/mask/breath,
+/obj/item/clothing/mask/breath,
+/obj/item/clothing/mask/breath,
+/obj/item/tank/emergency_oxygen/engi,
+/obj/item/tank/emergency_oxygen/engi,
+/obj/item/tank/emergency_oxygen/engi,
+/obj/item/tank/emergency_oxygen/engi,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"aW" = (
/obj/item/radio/intercom{
dir = 8;
name = "station intercom (General)";
pixel_x = -28
},
-/obj/machinery/light/spot{
- tag = "icon-tube1 (WEST)";
- icon_state = "tube1";
- dir = 8
- },
/obj/structure/chair/comfy/shuttle{
dir = 4
},
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
-/area/shuttle/escape)
-"aT" = (
-/obj/structure/closet/walllocker/emerglocker{
- pixel_x = 28
- },
-/obj/machinery/light/spot{
- tag = "icon-tube1 (EAST)";
- icon_state = "tube1";
- dir = 4
- },
-/obj/structure/chair/comfy/shuttle{
- dir = 8
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
-/area/shuttle/escape)
-"aU" = (
-/obj/structure/table,
-/obj/item/storage/firstaid/fire,
-/obj/item/storage/firstaid/regular{
- pixel_x = 2;
- pixel_y = 3
- },
-/obj/item/extinguisher,
-/obj/item/crowbar,
-/obj/machinery/light/spot{
- tag = "icon-tube1 (WEST)";
- icon_state = "tube1";
- dir = 8
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
-/area/shuttle/escape)
-"aV" = (
-/obj/machinery/door/airlock/shuttle{
- aiControlDisabled = 1;
- hackProof = 1;
- id_tag = "s_docking_airlock";
- name = "Shuttle Hatch"
- },
-/turf/simulated/shuttle/floor,
-/area/shuttle/escape)
-"aW" = (
-/obj/machinery/status_display{
- pixel_y = -30
- },
-/obj/machinery/light/spot,
-/turf/simulated/shuttle/floor,
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aX" = (
-/obj/structure/noticeboard,
-/turf/simulated/shuttle/wall{
- icon_state = "swall12";
- dir = 2
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
},
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aY" = (
-/obj/machinery/door/airlock/shuttle{
- aiControlDisabled = 1;
- hackProof = 1;
- id_tag = null;
- name = "Shuttle Cargo Hatch"
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/obj/structure/table/reinforced,
+/obj/machinery/recharger,
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "redcorner"
},
/area/shuttle/escape)
"aZ" = (
@@ -383,12 +395,9 @@
},
/area/shuttle/escape)
"ba" = (
-/obj/structure/grille,
-/obj/structure/window/full/shuttle{
- icon_state = "15"
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "neutralfull"
},
/area/shuttle/escape)
"bb" = (
@@ -406,124 +415,82 @@
/turf/simulated/floor/plating,
/area/shuttle/escape)
"bd" = (
-/obj/machinery/door/airlock/medical/glass{
- id_tag = null;
- name = "Escape Shuttle Infirmary";
- req_access_txt = "0"
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "neutralcorner"
},
-/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"be" = (
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/obj/machinery/door/airlock/shuttle/glass{
+ name = "Emergency Airlock Access";
+ req_one_access_txt = "2;19"
},
+/turf/simulated/floor/plasteel,
/area/shuttle/escape)
"bf" = (
-/obj/structure/closet/crate,
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/turf/simulated/floor/plasteel{
+ icon_state = "neutralcorner"
},
/area/shuttle/escape)
"bg" = (
-/obj/structure/table,
-/obj/item/storage/firstaid/o2{
- layer = 2.8;
- pixel_x = 4;
- pixel_y = 6
- },
-/obj/item/storage/firstaid/regular{
- pixel_x = 2;
- pixel_y = 6
- },
-/obj/item/storage/firstaid/regular{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/item/bodybag{
- pixel_x = 5
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ icon_state = "neutral"
},
/area/shuttle/escape)
"bh" = (
-/obj/machinery/vending/wallmed{
- layer = 3.3;
- name = "Emergency NanoMed";
- pixel_x = 28;
- pixel_y = 0;
- req_access_txt = "0"
- },
-/obj/structure/bed/roller,
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "neutralcorner"
},
/area/shuttle/escape)
"bi" = (
-/obj/structure/closet/cardboard,
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/obj/machinery/door/airlock/external{
+ id_tag = "s_docking_airlock"
},
+/obj/structure/fans/tiny,
+/turf/simulated/floor/plasteel,
/area/shuttle/escape)
"bj" = (
-/obj/machinery/light/spot{
- tag = "icon-tube1 (EAST)";
- icon_state = "tube1";
- dir = 4
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/obj/machinery/door/airlock/security/glass{
+ name = "Escape Shuttle Cell";
+ req_access_txt = "2"
},
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"bk" = (
-/obj/machinery/status_display{
- pixel_x = -30;
- pixel_y = 0
- },
-/obj/machinery/light/spot{
- tag = "icon-tube1 (WEST)";
- icon_state = "tube1";
- dir = 8
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "redcorner"
},
/area/shuttle/escape)
"bl" = (
-/obj/item/radio/intercom{
- dir = 4;
- name = "station intercom (General)";
- pixel_x = 28
- },
-/obj/structure/bed/roller,
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "neutral"
},
/area/shuttle/escape)
"bm" = (
-/obj/machinery/mech_bay_recharge_port,
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "neutralcorner"
},
/area/shuttle/escape)
"bn" = (
/turf/simulated/floor/mech_bay_recharge_floor,
/area/shuttle/escape)
"bo" = (
-/obj/machinery/recharge_station,
-/turf/simulated/shuttle/floor{
- icon_state = "floor2"
+/obj/machinery/door/airlock/shuttle{
+ aiControlDisabled = 1;
+ hackProof = 1;
+ id_tag = "s_docking_airlock";
+ name = "Shuttle Hatch"
},
+/turf/simulated/floor/plasteel,
/area/shuttle/escape)
"bp" = (
-/obj/machinery/sleeper{
- tag = "icon-sleeper (NORTH)";
- icon_state = "sleeper";
- dir = 1
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
+/obj/structure/table/reinforced,
+/obj/machinery/recharger,
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"bq" = (
/turf/space,
@@ -533,11 +500,11 @@
},
/area/shuttle/escape)
"br" = (
-/obj/structure/window/reinforced{
- dir = 1
+/obj/item/twohanded/required/kirbyplants,
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "redcorner"
},
-/obj/structure/shuttle/engine/heater,
-/turf/simulated/shuttle/plating,
/area/shuttle/escape)
"bs" = (
/turf/simulated/shuttle/wall{
@@ -569,6 +536,571 @@
/obj/structure/shuttle/engine/propulsion,
/turf/simulated/shuttle/plating,
/area/shuttle/escape)
+"bx" = (
+/obj/item/twohanded/required/kirbyplants,
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 28
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "neutralcorner"
+ },
+/area/shuttle/escape)
+"by" = (
+/obj/structure/table,
+/obj/item/storage/firstaid,
+/obj/effect/decal/warning_stripes/yellow/hollow,
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bz" = (
+/obj/machinery/light,
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bA" = (
+/obj/machinery/status_display{
+ pixel_y = -32
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bB" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bC" = (
+/obj/machinery/door/airlock/command/glass{
+ name = "Escape Shuttle Cockpit";
+ req_access_txt = "0";
+ req_one_access_txt = "2;19"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "neutralfull"
+ },
+/area/shuttle/escape)
+"bD" = (
+/obj/machinery/door/airlock/shuttle{
+ aiControlDisabled = 1;
+ hackProof = 1;
+ id_tag = "s_docking_airlock";
+ name = "Shuttle Hatch"
+ },
+/obj/docking_port/mobile/emergency{
+ dir = 4;
+ dwidth = 11;
+ height = 18;
+ timid = 1;
+ width = 29
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bE" = (
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bF" = (
+/obj/machinery/light{
+ dir = 1;
+ on = 1
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "neutral"
+ },
+/area/shuttle/escape)
+"bG" = (
+/obj/machinery/mech_bay_recharge_port,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bH" = (
+/obj/machinery/computer/mech_bay_power_console,
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bI" = (
+/obj/structure/table,
+/obj/item/weldingtool/largetank{
+ pixel_x = 4;
+ pixel_y = -4
+ },
+/obj/item/clothing/glasses/welding{
+ pixel_y = 10
+ },
+/obj/machinery/light/small{
+ dir = 4;
+ pixel_y = 8
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bJ" = (
+/obj/item/twohanded/required/kirbyplants,
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bK" = (
+/obj/item/twohanded/required/kirbyplants,
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 4
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bL" = (
+/obj/structure/reagent_dispensers/fueltank/chem{
+ pixel_x = -32;
+ pixel_y = 0
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bM" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "browncorner"
+ },
+/area/shuttle/escape)
+"bN" = (
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "browncorner"
+ },
+/area/shuttle/escape)
+"bO" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bP" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bQ" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bR" = (
+/obj/structure/flora/ausbushes/grassybush,
+/obj/structure/flora/ausbushes/lavendergrass,
+/obj/structure/flora/ausbushes/ppflowers,
+/obj/structure/flora/ausbushes/sunnybush,
+/obj/structure/window/full/shuttle,
+/turf/simulated/floor/grass,
+/area/shuttle/escape)
+"bS" = (
+/obj/machinery/door/airlock/shuttle/glass{
+ name = "Shuttle Cargo Hatch"
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"bT" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "brown"
+ },
+/area/shuttle/escape)
+"bU" = (
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "brown"
+ },
+/area/shuttle/escape)
+"bV" = (
+/obj/structure/reagent_dispensers/watertank,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"bW" = (
+/obj/machinery/status_display,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall3";
+ dir = 2
+ },
+/area/shuttle/escape)
+"bX" = (
+/obj/machinery/ai_status_display,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall3";
+ dir = 2
+ },
+/area/shuttle/escape)
+"bY" = (
+/obj/structure/flora/ausbushes/grassybush,
+/obj/structure/flora/ausbushes/lavendergrass,
+/obj/structure/flora/ausbushes/ywflowers,
+/obj/structure/flora/ausbushes/fernybush,
+/obj/structure/window/full/shuttle,
+/turf/simulated/floor/grass,
+/area/shuttle/escape)
+"bZ" = (
+/obj/structure/table,
+/obj/machinery/cell_charger,
+/obj/item/stock_parts/cell/high,
+/obj/machinery/light/small{
+ tag = "icon-bulb1 (WEST)";
+ icon_state = "bulb1";
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"ca" = (
+/obj/structure/closet/crate,
+/obj/item/storage/toolbox/emergency,
+/obj/item/storage/toolbox/emergency,
+/obj/item/flashlight/flare,
+/obj/item/flashlight/flare,
+/obj/item/crowbar,
+/obj/item/wrench,
+/obj/item/radio,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cb" = (
+/obj/item/twohanded/required/kirbyplants,
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"cc" = (
+/obj/structure/extinguisher_cabinet,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall3";
+ dir = 2
+ },
+/area/shuttle/escape)
+"cd" = (
+/obj/item/radio/intercom{
+ dir = 8;
+ name = "station intercom (General)";
+ pixel_x = -28
+ },
+/obj/machinery/recharge_station,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"ce" = (
+/obj/structure/closet/crate/engineering,
+/obj/item/storage/toolbox/electrical{
+ pixel_x = -4;
+ pixel_y = 4
+ },
+/obj/item/storage/toolbox/emergency,
+/obj/item/storage/toolbox/mechanical{
+ pixel_x = 4;
+ pixel_y = -4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cf" = (
+/obj/structure/extinguisher_cabinet{
+ pixel_x = -28
+ },
+/obj/machinery/recharge_station,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cg" = (
+/turf/simulated/floor/plasteel{
+ tag = "icon-browncorner (EAST)";
+ icon_state = "browncorner";
+ dir = 4
+ },
+/area/shuttle/escape)
+"ch" = (
+/turf/simulated/floor/plasteel{
+ dir = 1;
+ icon_state = "browncorner";
+ tag = "icon-browncorner (EAST)"
+ },
+/area/shuttle/escape)
+"ci" = (
+/obj/structure/closet/crate/medical,
+/obj/item/storage/firstaid/regular,
+/obj/item/storage/firstaid/o2{
+ pixel_x = 2;
+ pixel_y = -2
+ },
+/obj/item/storage/firstaid/toxin{
+ pixel_x = -2;
+ pixel_y = 4
+ },
+/obj/machinery/light/small,
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cj" = (
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"ck" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cl" = (
+/obj/machinery/door/airlock/medical/glass{
+ id_tag = null;
+ name = "Escape Shuttle Infirmary";
+ req_access_txt = "0"
+ },
+/obj/effect/decal/warning_stripes/south,
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"cm" = (
+/obj/structure/sign/greencross,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall12";
+ dir = 2
+ },
+/area/shuttle/escape)
+"cn" = (
+/obj/structure/sign/greencross,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall3";
+ dir = 2
+ },
+/area/shuttle/escape)
+"co" = (
+/obj/machinery/sleeper{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cp" = (
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cq" = (
+/obj/machinery/sleeper,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cr" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel,
+/area/shuttle/escape)
+"cs" = (
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue (NORTH)";
+ icon_state = "whiteblue";
+ dir = 1
+ },
+/area/shuttle/escape)
+"ct" = (
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 28
+ },
+/obj/machinery/light/small{
+ dir = 4;
+ pixel_y = 8
+ },
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue (SOUTHEAST)";
+ icon_state = "whiteblue";
+ dir = 6
+ },
+/area/shuttle/escape)
+"cu" = (
+/obj/machinery/door/airlock/medical/glass{
+ id_tag = null;
+ name = "Escape Shuttle Infirmary";
+ req_access_txt = "0"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 8;
+ icon_state = "neutralfull"
+ },
+/area/shuttle/escape)
+"cv" = (
+/turf/simulated/floor/plasteel{
+ icon_state = "white"
+ },
+/area/shuttle/escape)
+"cw" = (
+/obj/structure/bed/roller,
+/obj/machinery/iv_drip,
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue (EAST)";
+ icon_state = "whiteblue";
+ dir = 4
+ },
+/area/shuttle/escape)
+"cx" = (
+/obj/structure/table/reinforced,
+/obj/item/reagent_containers/iv_bag/blood/random,
+/obj/item/reagent_containers/iv_bag/blood/random,
+/obj/item/reagent_containers/iv_bag/blood/random,
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue (EAST)";
+ icon_state = "whiteblue";
+ dir = 4
+ },
+/area/shuttle/escape)
+"cy" = (
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue";
+ icon_state = "whiteblue"
+ },
+/area/shuttle/escape)
+"cz" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/firstaid/o2{
+ pixel_x = -3;
+ pixel_y = -3
+ },
+/obj/item/storage/firstaid/regular,
+/obj/item/storage/firstaid/regular{
+ pixel_x = 3;
+ pixel_y = 3
+ },
+/turf/simulated/floor/plasteel{
+ tag = "icon-whiteblue (NORTHEAST)";
+ icon_state = "whiteblue";
+ dir = 5
+ },
+/area/shuttle/escape)
+"cA" = (
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ icon_state = "bot";
+ dir = 1
+ },
+/area/shuttle/escape)
+"cB" = (
+/obj/structure/table/reinforced,
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/obj/item/reagent_containers/food/drinks/mug/med,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cC" = (
+/obj/item/flag/med,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cD" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/backpack/medic,
+/obj/item/storage/belt/medical,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cE" = (
+/obj/structure/bed/roller,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cF" = (
+/obj/item/radio/intercom{
+ dir = 4;
+ name = "Station Intercom (General)";
+ pixel_x = 29;
+ pixel_y = -30
+ },
+/obj/structure/bed/roller,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cG" = (
+/obj/structure/table/reinforced,
+/obj/item/clothing/gloves/color/latex/nitrile,
+/obj/item/clothing/mask/breath,
+/turf/simulated/floor/plasteel{
+ dir = 2;
+ icon_state = "cmo"
+ },
+/area/shuttle/escape)
+"cH" = (
+/turf/simulated/shuttle/wall{
+ icon_state = "wall3"
+ },
+/area/shuttle/escape)
(1,1,1) = {"
aa
@@ -576,23 +1108,28 @@ aa
aa
aa
aa
-aa
ab
aq
aq
-aM
-aP
-aR
aq
-aE
-aK
+bo
+aP
+bD
+aq
aQ
+aK
+aE
aq
-aV
-aP
-aB
-ac
+bo
aq
+bo
+aq
+aq
+aQ
+aE
+aq
+aq
+bt
bq
aa
"}
@@ -602,309 +1139,524 @@ aa
aa
aa
aa
-aa
av
-az
aG
+aW
+az
aH
av
-am
-aS
-aC
-aC
-aC
-aU
-am
+bE
+bJ
+bP
+bP
+bP
+cb
+bE
+cj
+bE
+cb
+bP
+bP
+bP
+cA
+aV
av
-be
-bi
-bm
-ay
-bq
+bu
+bw
"}
(3,1,1) = {"
aa
aa
aa
aa
-ab
-aq
-aw
-aA
+aa
+ac
+aO
aH
aH
-av
-am
-am
-am
-am
-am
-am
-am
-aX
-be
-be
-bn
-br
+aH
+bj
+bg
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+bB
+bb
+bu
bw
"}
(4,1,1) = {"
aa
aa
+aa
+aa
ab
-ac
-ae
-ar
-av
-aO
+aw
+aI
+aH
aH
aN
-av
-am
-aD
-aD
-aD
-aD
-am
-am
-aY
-be
-be
-bo
-br
+bb
+bg
+ba
+bQ
+bQ
+bQ
+bQ
+bQ
+ba
+bQ
+bQ
+bQ
+bQ
+bQ
+ba
+bB
+bc
+bu
bw
"}
(5,1,1) = {"
-aa
ab
-ae
-ak
-ao
-as
-av
-aO
-aH
-aN
-av
-am
-aE
-aK
-aK
-aQ
-am
-am
-av
-bf
-bj
-bo
-br
-bw
-"}
-(6,1,1) = {"
-ab
-ae
-ah
-ai
-am
-am
-av
+aq
ac
-aI
-aE
-ba
-am
-aC
-aC
-aC
-aC
-am
-aW
-aZ
-aq
-aq
aq
bs
-bv
+aw
+aO
+aH
+aH
+aN
+bc
+bg
+ba
+bR
+bW
+bY
+cc
+bR
+ba
+bY
+cc
+bR
+bX
+bY
+ba
+bB
+av
+cH
+cH
+"}
+(6,1,1) = {"
+av
+ae
+am
+ar
+ay
+av
+aJ
+aX
+aH
+bp
+av
+bg
+ba
+bP
+bP
+bP
+bP
+bP
+ba
+bP
+cr
+bP
+bP
+bP
+ba
+bB
+av
+bu
+bw
"}
(7,1,1) = {"
ac
af
-ai
-am
-am
-am
-ax
-am
-am
-am
-am
-am
-am
-am
-am
-am
-am
-am
-ac
-aa
-aa
-aa
-aa
-aa
-"}
-(8,1,1) = {"
-ad
-ag
-aj
-ai
-am
-at
-av
-aD
-aD
-aD
-aD
-am
-aD
-aD
-aD
-aD
-am
-aW
+an
+as
+aA
aZ
aq
+ac
+bj
aq
-aq
-bt
-bq
+aw
+bF
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+bB
+ac
+bu
+bw
"}
-(9,1,1) = {"
-aa
-ad
+(8,1,1) = {"
+ac
ag
+ao
an
-ap
-au
-ay
-aE
-aK
-aK
-aQ
-am
-aE
-aK
-aK
-aQ
-am
-am
+an
+aD
+aL
+aY
+bk
+br
ac
bg
-bk
-bp
+ba
+bQ
+bQ
+bQ
+bQ
+bQ
+ba
+bQ
+bQ
+bQ
+bQ
+bQ
+ba
+bB
+av
+cH
+cH
+"}
+(9,1,1) = {"
+ac
+ah
+ao
+an
+an
+aF
+aM
+ba
+ba
+bg
+bC
+bg
+ba
+bR
+bX
+bY
+cc
+bR
+ba
+bY
+cc
+bR
+bW
+bY
+ba
+bB
+bb
bu
bw
"}
(10,1,1) = {"
-aa
-aa
-ad
ac
-ag
-am
-av
-aC
-aC
-aC
-aC
-am
-aC
-aC
-aC
-aC
-am
-am
-bd
-aJ
-aJ
-aJ
+ai
+ao
+an
+an
+aF
+aM
+ba
+ba
+bg
+bC
+bg
+ba
+bP
+bP
+bP
+bP
+bP
+ba
+bP
+bP
+bP
+bP
+bP
+ba
+bB
+bc
bu
bw
"}
(11,1,1) = {"
+ac
+aj
+ao
+at
+an
+aD
+aR
+bd
+bf
+bx
+ac
+bg
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+ba
+bB
+av
+cH
+cH
+"}
+(12,1,1) = {"
+ac
+ak
+an
+au
+aB
+aZ
+aq
+be
+be
+aq
+aw
+aV
+bK
+bE
+bE
+bQ
+bQ
+bQ
+ck
+bQ
+bQ
+ba
+ba
+bQ
+ck
+aV
+ac
+bu
+bw
+"}
+(13,1,1) = {"
+av
+al
+ap
+ax
+aC
+av
+aS
+bf
+bd
+by
+aZ
+aq
+aq
+bS
+bS
+aq
+aq
+aq
+aP
+cn
+ac
+cu
+cu
+ac
+bW
+aq
+aw
+bu
+bw
+"}
+(14,1,1) = {"
+ad
+aq
+ac
+aq
+aP
+aw
+aT
+bg
+bl
+bz
+av
+bG
+bL
+bE
+bE
+bZ
+cd
+cf
+av
+co
+cs
+cv
+cv
+cy
+cB
+cD
+av
+cH
+cH
+"}
+(15,1,1) = {"
aa
aa
aa
aa
ad
-aq
aw
-aF
-am
-am
-am
-am
-am
-am
-am
-am
-am
-am
+aU
+bg
+bl
+bA
+av
+bn
+bM
+bT
+bT
+bT
+bT
+cg
+cl
+cp
+cs
+cv
+cv
+cy
+cp
+cE
bb
-aJ
-aJ
-bp
bu
bw
"}
-(12,1,1) = {"
+(16,1,1) = {"
aa
aa
aa
aa
aa
+ac
+aU
+bg
+bl
+bB
+av
+bH
+bN
+bU
+bU
+bU
+bU
+ch
+cl
+cp
+cs
+cv
+cv
+cy
+cp
+cF
+bc
+bu
+bw
+"}
+(17,1,1) = {"
+aa
+aa
+aa
+aa
aa
av
-aD
-aL
-aD
-aD
-aD
-aT
-aD
-aD
-aD
-am
-am
-bc
+aV
bh
-bl
-aJ
-ay
-bv
+bm
+aV
+av
+bI
+bO
+bV
+aV
+ca
+ce
+ci
+cm
+cq
+ct
+cw
+cx
+cz
+cC
+cG
+av
+bu
+bw
"}
-(13,1,1) = {"
-aa
+(18,1,1) = {"
aa
aa
aa
aa
aa
ad
-aq
-aq
ac
+bi
+bi
+ac
+bs
aq
-aq
-aq
-aE
-aK
aQ
+aK
+aK
+aK
+aE
aq
-ac
-aq
+bs
aq
aq
+aQ
+aK
+aK
+aE
aq
+bs
bv
aa
"}
diff --git a/_maps/map_files/shuttles/emergency_old.dmm b/_maps/map_files/shuttles/emergency_old.dmm
index f4a2b0c7754..b8b49da71e5 100644
--- a/_maps/map_files/shuttles/emergency_old.dmm
+++ b/_maps/map_files/shuttles/emergency_old.dmm
@@ -38,7 +38,7 @@
/area/shuttle/escape)
"ah" = (
/obj/machinery/computer/security{
- network = list("SS13","Research Outpost","Mining Outpost","Telecomms")
+ network = list("SS13","Telecomms","Research Outpost","Mining Outpost")
},
/turf/simulated/shuttle/floor,
/area/shuttle/escape)
@@ -192,9 +192,7 @@
/obj/structure/chair/comfy/shuttle{
dir = 4
},
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
+/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"aF" = (
/obj/structure/grille,
@@ -214,33 +212,6 @@
icon_state = "floor3"
},
/area/shuttle/escape)
-"aH" = (
-/obj/structure/table,
-/obj/item/storage/firstaid/regular{
- pixel_x = 2;
- pixel_y = 6
- },
-/obj/item/storage/firstaid/regular{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/item/bodybag{
- pixel_x = 5
- },
-/obj/item/radio/intercom{
- dir = 4;
- name = "station intercom (General)";
- pixel_x = 28
- },
-/obj/item/storage/firstaid/o2{
- layer = 2.8;
- pixel_x = 4;
- pixel_y = 6
- },
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
-/area/shuttle/escape)
"aI" = (
/turf/simulated/shuttle/floor{
icon_state = "floor3"
@@ -311,10 +282,6 @@
icon_state = "floor3"
},
/area/shuttle/escape)
-"aO" = (
-/obj/machinery/recharge_station,
-/turf/simulated/shuttle/floor,
-/area/shuttle/escape)
"aP" = (
/obj/machinery/door/airlock/shuttle{
aiControlDisabled = 1;
@@ -346,10 +313,11 @@
/turf/simulated/floor/plating,
/area/shuttle/escape)
"aT" = (
-/obj/machinery/door/airlock/medical/glass{
+/obj/machinery/door/airlock/shuttle{
+ aiControlDisabled = 1;
+ hackProof = 1;
id_tag = null;
- name = "Escape Shuttle Infirmary";
- req_access_txt = "0"
+ name = "Shuttle Cargo Hatch"
},
/turf/simulated/shuttle/floor{
icon_state = "floor3"
@@ -363,11 +331,12 @@
},
/area/shuttle/escape)
"aV" = (
-/obj/machinery/door/airlock/security/glass{
- name = "Escape Shuttle Cell";
- req_access_txt = "2"
+/obj/machinery/door/airlock/medical/glass{
+ id_tag = null;
+ name = "Escape Shuttle Infirmary";
+ req_access_txt = "0"
},
-/turf/simulated/shuttle/floor4,
+/turf/simulated/shuttle/floor,
/area/shuttle/escape)
"aW" = (
/obj/machinery/door/airlock/shuttle{
@@ -376,14 +345,12 @@
id_tag = "s_docking_airlock";
name = "Shuttle Hatch"
},
-/turf/simulated/shuttle/floor{
- icon_state = "floor3"
- },
+/turf/simulated/floor/plating,
/area/shuttle/escape)
"aX" = (
-/obj/structure/bed/roller,
+/obj/structure/closet/crate,
/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+ icon_state = "floor2"
},
/area/shuttle/escape)
"aZ" = (
@@ -394,30 +361,19 @@
/turf/simulated/shuttle/floor4,
/area/shuttle/escape)
"bb" = (
-/obj/machinery/sleeper{
- icon_state = "sleeper-open";
- dir = 4
- },
+/obj/structure/closet/cardboard,
/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+ icon_state = "floor2"
},
/area/shuttle/escape)
"bc" = (
-/obj/structure/bed/roller,
-/obj/machinery/vending/wallmed{
- layer = 3.3;
- name = "Emergency NanoMed";
- pixel_x = 28;
- pixel_y = 0;
- req_access_txt = "0"
- },
/obj/machinery/light/spot{
tag = "icon-tube1 (EAST)";
icon_state = "tube1";
dir = 4
},
/turf/simulated/shuttle/floor{
- icon_state = "floor3"
+ icon_state = "floor2"
},
/area/shuttle/escape)
"bd" = (
@@ -430,7 +386,9 @@
icon_state = "tube1";
dir = 8
},
-/turf/simulated/shuttle/floor4,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor3"
+ },
/area/shuttle/escape)
"be" = (
/obj/item/radio/intercom{
@@ -438,16 +396,17 @@
name = "station intercom (General)";
pixel_x = 28
},
-/turf/simulated/shuttle/floor4,
-/area/shuttle/escape)
-"bf" = (
-/obj/machinery/sleeper{
- dir = 4
- },
+/obj/structure/bed/roller,
/turf/simulated/shuttle/floor{
icon_state = "floor3"
},
/area/shuttle/escape)
+"bf" = (
+/obj/machinery/mech_bay_recharge_port,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor2"
+ },
+/area/shuttle/escape)
"bh" = (
/obj/structure/chair/comfy/shuttle{
dir = 1
@@ -492,6 +451,124 @@
/obj/structure/shuttle/engine/propulsion,
/turf/simulated/shuttle/plating,
/area/shuttle/escape)
+"db" = (
+/obj/machinery/door/airlock/security/glass{
+ name = "Escape Shuttle Cell";
+ req_access_txt = "2"
+ },
+/turf/simulated/floor/plating,
+/area/shuttle/escape)
+"ev" = (
+/obj/machinery/sleeper{
+ tag = "icon-sleeper (NORTH)";
+ icon_state = "sleeper";
+ dir = 1
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor3"
+ },
+/area/shuttle/escape)
+"iM" = (
+/obj/structure/table,
+/obj/item/storage/firstaid/o2{
+ layer = 2.8;
+ pixel_x = 4;
+ pixel_y = 6
+ },
+/obj/item/storage/firstaid/regular{
+ pixel_x = 2;
+ pixel_y = 6
+ },
+/obj/item/storage/firstaid/regular{
+ pixel_x = -2;
+ pixel_y = 4
+ },
+/obj/item/bodybag{
+ pixel_x = 5
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor3"
+ },
+/area/shuttle/escape)
+"kP" = (
+/turf/simulated/shuttle/wall{
+ tag = "icon-swall7";
+ icon_state = "swall7";
+ dir = 2
+ },
+/area/shuttle/escape)
+"lJ" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/simulated/shuttle/floor4,
+/area/shuttle/escape)
+"mk" = (
+/obj/machinery/status_display{
+ pixel_y = 30
+ },
+/obj/machinery/light/spot{
+ tag = "icon-tube1 (NORTH)";
+ icon_state = "tube1";
+ dir = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/simulated/shuttle/floor4,
+/area/shuttle/escape)
+"rj" = (
+/obj/machinery/vending/wallmed{
+ layer = 3.3;
+ name = "Emergency NanoMed";
+ pixel_x = 28;
+ pixel_y = 0;
+ req_access_txt = "0"
+ },
+/obj/structure/bed/roller,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor3"
+ },
+/area/shuttle/escape)
+"xo" = (
+/obj/machinery/recharge_station,
+/turf/simulated/shuttle/floor{
+ icon_state = "floor2"
+ },
+/area/shuttle/escape)
+"zT" = (
+/obj/structure/noticeboard,
+/turf/simulated/shuttle/wall{
+ icon_state = "swall12";
+ dir = 2
+ },
+/area/shuttle/escape)
+"Bs" = (
+/obj/machinery/door/airlock/shuttle{
+ aiControlDisabled = 1;
+ hackProof = 1;
+ id_tag = "s_docking_airlock";
+ name = "Shuttle Hatch"
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor2"
+ },
+/area/shuttle/escape)
+"DZ" = (
+/turf/simulated/shuttle/floor{
+ icon_state = "floor2"
+ },
+/area/shuttle/escape)
+"OC" = (
+/obj/structure/grille,
+/obj/structure/window/full/shuttle{
+ icon_state = "15"
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor3"
+ },
+/area/shuttle/escape)
+"XL" = (
+/turf/simulated/floor/mech_bay_recharge_floor,
+/area/shuttle/escape)
(1,1,1) = {"
aa
@@ -504,7 +581,7 @@ ab
ar
ar
aW
-ar
+kP
ak
ar
aD
@@ -512,8 +589,8 @@ aF
aJ
ar
aP
-ar
-aW
+kP
+Bs
ac
ar
bi
@@ -527,10 +604,10 @@ aa
aa
aa
aw
-aA
+lJ
aE
-aI
-aA
+ba
+aw
an
aL
aA
@@ -538,8 +615,8 @@ aA
aA
aN
an
-aR
-aI
+aw
+DZ
bb
bf
az
@@ -553,7 +630,10 @@ aa
ab
ar
ax
-aB
+mk
+ba
+ba
+aw
an
an
an
@@ -561,13 +641,10 @@ an
an
an
an
-an
-an
-an
-aS
-aI
-aI
-aI
+zT
+DZ
+DZ
+XL
bj
bo
"}
@@ -579,10 +656,10 @@ ac
ae
as
aw
-aC
-aC
-aC
-aC
+aZ
+ba
+bh
+aw
an
aC
aC
@@ -591,9 +668,9 @@ aC
an
an
aT
-aI
-aI
-aI
+DZ
+DZ
+xo
bj
bo
"}
@@ -605,10 +682,10 @@ al
ap
at
aw
-aD
-aF
-aF
-aJ
+aZ
+ba
+bh
+aw
an
aD
aF
@@ -616,10 +693,10 @@ aF
aJ
an
an
-ac
+aw
aX
bc
-aH
+xo
bj
bo
"}
@@ -631,10 +708,10 @@ ai
an
an
aw
-aA
-aA
-aA
-aA
+ac
+db
+aD
+OC
an
aA
aA
@@ -721,9 +798,9 @@ aJ
an
an
ac
-aZ
+iM
bd
-bh
+ev
bm
bo
"}
@@ -747,9 +824,9 @@ aA
an
an
aV
-ba
-ba
-bh
+aI
+aI
+aI
bm
bo
"}
@@ -773,9 +850,9 @@ an
an
an
aR
-aZ
-ba
-bh
+aI
+aI
+ev
bm
bo
"}
@@ -796,12 +873,12 @@ aM
aC
aC
aC
-aO
-aO
+an
+an
aS
-aZ
+rj
be
-bh
+aI
az
bn
"}
diff --git a/_maps/metastation.dm b/_maps/metastation.dm
index ad4c4370d74..0941ffc453a 100644
--- a/_maps/metastation.dm
+++ b/_maps/metastation.dm
@@ -16,22 +16,14 @@ z7 = empty space
#if !defined(USING_MAP_DATUM)
#include "map_files\MetaStation\MetaStation.v41A.II.dmm"
#include "map_files\MetaStation\z2.dmm"
- #include "map_files\MetaStation\z3.dmm"
- #include "map_files\MetaStation\z4.dmm"
#include "map_files\generic\Lavaland.dmm"
- #include "map_files\generic\z6.dmm"
- #include "map_files\generic\z7.dmm"
#define MAP_FILE "MetaStation.v41A.II.dmm"
#define MAP_NAME "MetaStation"
#define MAP_TRANSITION_CONFIG list(\
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
-DECLARE_LEVEL(TELECOMMS, CROSSLINKED, list(REACHABLE, BOOSTS_SIGNAL, AI_OK)),\
-DECLARE_LEVEL(DERELICT, CROSSLINKED, list(REACHABLE)),\
-DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)),\
-DECLARE_LEVEL(EMPTY_AREA, CROSSLINKED, list(REACHABLE)),\
-DECLARE_LEVEL(EMPTY_AREA_2, CROSSLINKED, list(REACHABLE)))
+DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
#define USING_MAP_DATUM /datum/map/metastation
diff --git a/_maps/test_all_maps.dm b/_maps/test_all_maps.dm
deleted file mode 100644
index 94bd9bac437..00000000000
--- a/_maps/test_all_maps.dm
+++ /dev/null
@@ -1,145 +0,0 @@
-// This is for Travis testing. DO NOT SET THIS AS THE GAME'S MAP NORMALLY!
-
-#if !defined(USING_MAP_DATUM)
- // Away missions
- #include "map_files\RandomZLevels\academy.dmm"
- #include "map_files\RandomZLevels\beach.dmm"
- #include "map_files\RandomZLevels\blackmarketpackers.dmm"
- #include "map_files\RandomZLevels\centcomAway.dmm"
- #include "map_files\RandomZLevels\evil_santa.dmm"
- #include "map_files\RandomZLevels\example.dmm"
- #include "map_files\RandomZLevels\moonoutpost19.dmm"
- #include "map_files\RandomZLevels\spacebattle.dmm"
- #include "map_files\RandomZLevels\spacehotel.dmm"
- #include "map_files\RandomZLevels\stationCollision.dmm"
- #include "map_files\RandomZLevels\terrorspiders.dmm"
- #include "map_files\RandomZLevels\undergroundoutpost45.dmm"
- #include "map_files\RandomZLevels\wildwest.dmm"
-
-
- // Lavaland Ruins
- #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_beach.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_clown_planet.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_winter.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_animal_hospital.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_ash_walker1.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk1.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk2.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk3.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_cube.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_cultaltar.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_dead_ratvar.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_envy.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_fountain_hall.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_gluttony.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_greed.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_hermit.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_hierophant.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_pizzaparty.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_pride.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_puzzle.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_random_ripley.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_seed_vault.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_sloth.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_survivalpod.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_swarmer_crash.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_syndicate_base1.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_ufo_crash.dmm"
- #include "map_files\RandomRuins\LavaRuins\lavaland_surface_xeno_nest.dmm"
-
-
- // Space Ruins
- #include "map_files\RandomRuins\SpaceRuins\abandonedzoo.dmm"
- #include "map_files\RandomRuins\SpaceRuins\asteroid1.dmm"
- #include "map_files\RandomRuins\SpaceRuins\asteroid2.dmm"
- #include "map_files\RandomRuins\SpaceRuins\asteroid3.dmm"
- #include "map_files\RandomRuins\SpaceRuins\asteroid4.dmm"
- #include "map_files\RandomRuins\SpaceRuins\asteroid5.dmm"
- #include "map_files\RandomRuins\SpaceRuins\deepstorage.dmm"
- #include "map_files\RandomRuins\SpaceRuins\derelict1.dmm"
- #include "map_files\RandomRuins\SpaceRuins\derelict2.dmm"
- #include "map_files\RandomRuins\SpaceRuins\derelict3.dmm"
- #include "map_files\RandomRuins\SpaceRuins\derelict4.dmm"
- #include "map_files\RandomRuins\SpaceRuins\derelict5.dmm"
- #include "map_files\RandomRuins\SpaceRuins\emptyshell.dmm"
- #include "map_files\RandomRuins\SpaceRuins\gasthelizards.dmm"
- #include "map_files\RandomRuins\SpaceRuins\intactemptyship.dmm"
- #include "map_files\RandomRuins\SpaceRuins\listeningpost.dmm"
- #include "map_files\RandomRuins\SpaceRuins\mechtransport.dmm"
- #include "map_files\RandomRuins\SpaceRuins\oldstation.dmm"
- #include "map_files\RandomRuins\SpaceRuins\onehalf.dmm"
- #include "map_files\RandomRuins\SpaceRuins\spacebar.dmm"
- #include "map_files\RandomRuins\SpaceRuins\turretedoutpost.dmm"
- #include "map_files\RandomRuins\SpaceRuins\way_home.dmm"
-
-
- // Shuttle Templates
- #include "map_files\shuttles\cargo_base.dmm"
- #include "map_files\shuttles\emergency_bar.dmm"
- #include "map_files\shuttles\emergency_clown.dmm"
- #include "map_files\shuttles\emergency_cramped.dmm"
- #include "map_files\shuttles\emergency_cyb.dmm"
- #include "map_files\shuttles\emergency_dept.dmm"
- #include "map_files\shuttles\emergency_meta.dmm"
- #include "map_files\shuttles\emergency_mil.dmm"
- #include "map_files\shuttles\emergency_narnar.dmm"
- #include "map_files\shuttles\emergency_old.dmm"
- #include "map_files\shuttles\ferry_base.dmm"
- #include "map_files\shuttles\ferry_meat.dmm"
-
- // Other templates
- #include "map_files\templates\spacehotel\n_01.dmm"
- #include "map_files\templates\spacehotel\n_02.dmm"
- #include "map_files\templates\spacehotel\n_03.dmm"
- #include "map_files\templates\spacehotel\n_04.dmm"
- #include "map_files\templates\spacehotel\n_05.dmm"
- #include "map_files\templates\spacehotel\n_06.dmm"
- #include "map_files\templates\spacehotel\n_07.dmm"
- #include "map_files\templates\spacehotel\n_08.dmm"
- #include "map_files\templates\spacehotel\n_09.dmm"
- #include "map_files\templates\spacehotel\n_10.dmm"
- #include "map_files\templates\spacehotel\n_11.dmm"
- #include "map_files\templates\spacehotel\n_12.dmm"
- #include "map_files\templates\spacehotel\n_13.dmm"
- #include "map_files\templates\spacehotel\n_14.dmm"
- #include "map_files\templates\spacehotel\n_15.dmm"
- #include "map_files\templates\spacehotel\n_16.dmm"
- #include "map_files\templates\spacehotel\n_17.dmm"
- #include "map_files\templates\spacehotel\n_18.dmm"
- #include "map_files\templates\spacehotel\n_19.dmm"
-
- #include "map_files\templates\spacehotel\s_01.dmm"
- #include "map_files\templates\spacehotel\s_02.dmm"
- #include "map_files\templates\spacehotel\s_03.dmm"
- #include "map_files\templates\spacehotel\s_04.dmm"
- #include "map_files\templates\spacehotel\s_05.dmm"
- #include "map_files\templates\spacehotel\s_06.dmm"
-
- #include "map_files\templates\light_floor_1.dmm"
- #include "map_files\templates\light_floor_2.dmm"
- #include "map_files\templates\light_floor_3.dmm"
- #include "map_files\templates\medium_shuttle1.dmm"
- #include "map_files\templates\medium_shuttle2.dmm"
- #include "map_files\templates\medium_shuttle3.dmm"
- #include "map_files\templates\shelter_1.dmm"
- #include "map_files\templates\shelter_2.dmm"
- #include "map_files\templates\small_asteroid_1.dmm"
- #include "map_files\templates\small_shuttle_1.dmm"
-
- // This is pointless, we don't run the server
- /*#define MAP_TRANSITION_CONFIG list(AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED,
- AWAY_MISSION = UNAFFECTED)
-
- #define USING_MAP_DATUM /datum/map*/
-
-#elif !defined(MAP_OVERRIDE)
- #warn a map has already been included.
-#endif
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 507142c0892..8dd95119aff 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -59,7 +59,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
for(var/mob/living/L in src) //ventcrawling is serious business
L.remove_ventcrawl()
L.forceMove(get_turf(src))
- QDEL_NULL(pipe_image) //we have to del it, or it might keep a ref somewhere else
+ QDEL_NULL(pipe_image) //we have to qdel it, or it might keep a ref somewhere else
return ..()
// Icons/overlays/underlays
@@ -343,3 +343,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
/obj/machinery/atmospherics/update_remote_sight(mob/user)
user.sight |= (SEE_TURFS|BLIND)
. = ..()
+
+//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
+/obj/machinery/atmospherics/proc/can_see_pipes()
+ return TRUE
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index c0ed34ef206..43b3c382c95 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -26,7 +26,6 @@
var/frequency = ATMOS_VENTSCRUB
var/id_tag = null
var/datum/radio_frequency/radio_connection
- var/advcontrol = 0//does this device listen to the AAC
settagwhitelist = list("id_tag")
@@ -75,7 +74,7 @@
/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
..()
-
+
if(!check_icon_cache())
return
@@ -192,7 +191,7 @@
return 1
/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["advcontrol"] && !advcontrol))
+ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return 0
if(signal.data["power"] != null)
on = text2num(signal.data["power"])
@@ -256,14 +255,5 @@
"}
/obj/machinery/atmospherics/unary/vent_scrubber/multitool_topic(var/mob/user, var/list/href_list, var/obj/O)
- if("toggleadvcontrol" in href_list)
- advcontrol = !advcontrol
- return TRUE
-
if("set_id" in href_list)
var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN)
if(!newid)
diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index 2cf3edfb275..ff9fb9a4ab1 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -127,20 +127,15 @@ GLOBAL_VAR_INIT(pipenetwarnings, 10)
member.air_temporary = new
member.air_temporary.volume = member.volume
- member.air_temporary.oxygen = air.oxygen*member.volume/air.volume
- member.air_temporary.nitrogen = air.nitrogen*member.volume/air.volume
- member.air_temporary.toxins = air.toxins*member.volume/air.volume
- member.air_temporary.carbon_dioxide = air.carbon_dioxide*member.volume/air.volume
+ member.air_temporary.oxygen = air.oxygen * member.volume / air.volume
+ member.air_temporary.nitrogen = air.nitrogen * member.volume / air.volume
+ member.air_temporary.toxins = air.toxins * member.volume / air.volume
+ member.air_temporary.carbon_dioxide = air.carbon_dioxide * member.volume / air.volume
+ member.air_temporary.sleeping_agent = air.sleeping_agent * member.volume / air.volume
+ member.air_temporary.agent_b = air.agent_b * member.volume / air.volume
member.air_temporary.temperature = air.temperature
- if(air.trace_gases.len)
- for(var/datum/gas/trace_gas in air.trace_gases)
- var/datum/gas/corresponding = new trace_gas.type()
- member.air_temporary.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*member.volume/air.volume
-
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
var/total_heat_capacity = air.heat_capacity()
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
@@ -228,7 +223,8 @@ GLOBAL_VAR_INIT(pipenetwarnings, 10)
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
- var/list/total_trace_gases = list()
+ var/total_sleeping_agent = 0
+ var/total_agent_b = 0
for(var/datum/gas_mixture/G in GL)
total_volume += G.volume
@@ -239,15 +235,8 @@ GLOBAL_VAR_INIT(pipenetwarnings, 10)
total_nitrogen += G.nitrogen
total_toxins += G.toxins
total_carbon_dioxide += G.carbon_dioxide
-
- if(G.trace_gases.len)
- for(var/datum/gas/trace_gas in G.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- total_trace_gases += corresponding
-
- corresponding.moles += trace_gas.moles
+ total_sleeping_agent += G.sleeping_agent
+ total_agent_b += G.agent_b
if(total_volume > 0)
@@ -259,18 +248,11 @@ GLOBAL_VAR_INIT(pipenetwarnings, 10)
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/G in GL)
- G.oxygen = total_oxygen*G.volume/total_volume
- G.nitrogen = total_nitrogen*G.volume/total_volume
- G.toxins = total_toxins*G.volume/total_volume
- G.carbon_dioxide = total_carbon_dioxide*G.volume/total_volume
+ G.oxygen = total_oxygen * G.volume / total_volume
+ G.nitrogen = total_nitrogen * G.volume / total_volume
+ G.toxins = total_toxins * G.volume / total_volume
+ G.carbon_dioxide = total_carbon_dioxide * G.volume / total_volume
+ G.sleeping_agent = total_sleeping_agent * G.volume / total_volume
+ G.agent_b = total_agent_b * G.volume / total_volume
G.temperature = temperature
-
- if(total_trace_gases.len)
- for(var/datum/gas/trace_gas in total_trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in G.trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- G.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*G.volume/total_volume
diff --git a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm
index 94983f62acd..7e304170e54 100644
--- a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm
+++ b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm
@@ -87,7 +87,7 @@
else return 1
/obj/machinery/atmospherics/pipe/simple/proc/burst()
- src.visible_message("\The [src] bursts!");
+ src.visible_message("\The [src] bursts!")
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(1,0, src.loc, 0)
diff --git a/code/LINDA/LINDA_fire.dm b/code/LINDA/LINDA_fire.dm
index 6ec505d9f9a..30c56f93cc8 100644
--- a/code/LINDA/LINDA_fire.dm
+++ b/code/LINDA/LINDA_fire.dm
@@ -176,7 +176,7 @@
if(istype(loc, /turf/simulated))
var/turf/simulated/T = loc
- if(T.to_be_destroyed)
+ if(T.to_be_destroyed && !T.changing_turf)
var/chance_of_deletion
if(T.heat_capacity) //beware of division by zero
chance_of_deletion = T.max_fire_temperature_sustained / T.heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0
diff --git a/code/LINDA/LINDA_system.dm b/code/LINDA/LINDA_system.dm
index c5bc65d3bf7..3c8633c2b91 100644
--- a/code/LINDA/LINDA_system.dm
+++ b/code/LINDA/LINDA_system.dm
@@ -142,7 +142,7 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5)
return
T.atmos_spawn_air(text, amount)
-/turf/simulated/proc/atmos_spawn_air(var/flag, var/amount)
+/turf/simulated/proc/atmos_spawn_air(flag, amount)
if(!text || !amount || !air)
return
@@ -156,17 +156,21 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5)
if(flag & LINDA_SPAWN_TOXINS)
G.toxins += amount
+
if(flag & LINDA_SPAWN_OXYGEN)
G.oxygen += amount
+
if(flag & LINDA_SPAWN_CO2)
G.carbon_dioxide += amount
+
if(flag & LINDA_SPAWN_NITROGEN)
G.nitrogen += amount
if(flag & LINDA_SPAWN_N2O)
- var/datum/gas/sleeping_agent/T = new
- T.moles += amount
- G.trace_gases += T
+ G.sleeping_agent += amount
+
+ if(flag & LINDA_SPAWN_AGENT_B)
+ G.agent_b += amount
if(flag & LINDA_SPAWN_AIR)
G.oxygen += MOLES_O2STANDARD * amount
diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm
index 72f77d2440f..acfa1983f72 100644
--- a/code/LINDA/LINDA_turf_tile.dm
+++ b/code/LINDA/LINDA_turf_tile.dm
@@ -19,20 +19,24 @@
GM.carbon_dioxide = carbon_dioxide
GM.nitrogen = nitrogen
GM.toxins = toxins
+ GM.sleeping_agent = sleeping_agent
+ GM.agent_b = agent_b
GM.temperature = temperature
return GM
-/turf/remove_air(amount as num)
+/turf/remove_air(amount)
var/datum/gas_mixture/GM = new
- var/sum = oxygen + carbon_dioxide + nitrogen + toxins
- if(sum>0)
- GM.oxygen = (oxygen/sum)*amount
- GM.carbon_dioxide = (carbon_dioxide/sum)*amount
- GM.nitrogen = (nitrogen/sum)*amount
- GM.toxins = (toxins/sum)*amount
+ var/sum = oxygen + carbon_dioxide + nitrogen + toxins + sleeping_agent + agent_b
+ if(sum > 0)
+ GM.oxygen = (oxygen / sum) * amount
+ GM.carbon_dioxide = (carbon_dioxide / sum) * amount
+ GM.nitrogen = (nitrogen / sum) * amount
+ GM.toxins = (toxins / sum) * amount
+ GM.sleeping_agent = (sleeping_agent / sum) * amount
+ GM.agent_b = (agent_b / sum) * amount
GM.temperature = temperature
@@ -53,7 +57,7 @@
var/temperature_archived //USED ONLY FOR SOLIDS
- var/atmos_overlay_type = "" //current active overlay
+ var/atmos_overlay_type = null //current active overlay
/turf/simulated/New()
..()
@@ -64,12 +68,14 @@
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
+ air.sleeping_agent = sleeping_agent
+ air.agent_b = agent_b
air.temperature = temperature
/turf/simulated/Destroy()
- visibilityChanged()
QDEL_NULL(active_hotspot)
+ QDEL_NULL(wet_overlay)
return ..()
/turf/simulated/assume_air(datum/gas_mixture/giver)
@@ -100,7 +106,7 @@
else
return ..()
-/turf/simulated/remove_air(amount as num)
+/turf/simulated/remove_air(amount)
if(air)
var/datum/gas_mixture/removed = null
@@ -155,7 +161,7 @@
var/turf/enemy_tile = get_step(src, direction)
- if(istype(enemy_tile,/turf/simulated))
+ if(istype(enemy_tile, /turf/simulated))
var/turf/simulated/enemy_simulated = enemy_tile
if(current_cycle > enemy_simulated.current_cycle)
@@ -211,7 +217,13 @@
if(planet_atmos) //share our air with the "atmosphere" "above" the turf
var/datum/gas_mixture/G = new
- G.copy_from_turf(src)
+ G.oxygen = oxygen
+ G.carbon_dioxide = carbon_dioxide
+ G.nitrogen = nitrogen
+ G.toxins = toxins
+ G.sleeping_agent = sleeping_agent
+ G.agent_b = agent_b
+ G.temperature = initial(temperature) // Temperature is modified at runtime; we only care about the turf's initial temperature
G.archive()
if(!air.compare(G))
if(!excited_group)
@@ -271,8 +283,7 @@
if(air.toxins > MOLES_PLASMA_VISIBLE)
return "plasma"
- var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases
- if(sleeping_agent && (sleeping_agent.moles > 1))
+ if(air.sleeping_agent > 1)
return "sleeping_agent"
return null
@@ -340,7 +351,7 @@
reset_cooldowns()
/datum/excited_group/proc/merge_groups(var/datum/excited_group/E)
- if(turf_list.len > E.turf_list.len)
+ if(length(turf_list) > length(E.turf_list))
SSair.excited_groups -= E
for(var/turf/simulated/T in E.turf_list)
T.excited_group = src
@@ -358,32 +369,26 @@
/datum/excited_group/proc/self_breakdown()
var/datum/gas_mixture/A = new
- var/datum/gas/sleeping_agent/S = new
- A.trace_gases += S
- for(var/turf/simulated/T in turf_list)
- A.oxygen += T.air.oxygen
- A.carbon_dioxide+= T.air.carbon_dioxide
- A.nitrogen += T.air.nitrogen
- A.toxins += T.air.toxins
- if(T.air.trace_gases.len)
- for(var/datum/gas/N in T.air.trace_gases)
- S.moles += N.moles
+ var/list/cached_turf_list = turf_list // cache for super speed
- for(var/turf/simulated/T in turf_list)
- T.air.oxygen = A.oxygen/turf_list.len
- T.air.carbon_dioxide= A.carbon_dioxide/turf_list.len
- T.air.nitrogen = A.nitrogen/turf_list.len
- T.air.toxins = A.toxins/turf_list.len
+ for(var/turf/simulated/T in cached_turf_list)
+ A.oxygen += T.air.oxygen
+ A.carbon_dioxide += T.air.carbon_dioxide
+ A.nitrogen += T.air.nitrogen
+ A.toxins += T.air.toxins
+ A.sleeping_agent += T.air.sleeping_agent
+ A.agent_b += T.air.agent_b
- if(S.moles > 0)
- if(T.air.trace_gases.len)
- for(var/datum/gas/G in T.air.trace_gases)
- G.moles = S.moles/turf_list.len
- else
- var/datum/gas/sleeping_agent/G = new
- G.moles = S.moles/turf_list.len
- T.air.trace_gases += G
+ var/turflen = length(cached_turf_list)
+
+ for(var/turf/simulated/T in cached_turf_list)
+ T.air.oxygen = A.oxygen / turflen
+ T.air.carbon_dioxide = A.carbon_dioxide / turflen
+ T.air.nitrogen = A.nitrogen / turflen
+ T.air.toxins = A.toxins / turflen
+ T.air.sleeping_agent = A.sleeping_agent / turflen
+ T.air.agent_b = A.agent_b / turflen
T.update_visuals()
diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm
index cbcf2c1dd90..e2068cecb89 100644
--- a/code/__DEFINES/MC.dm
+++ b/code/__DEFINES/MC.dm
@@ -32,17 +32,16 @@
// (Requires a MC restart to change)
#define SS_NO_FIRE 2
-//subsystem only runs on spare cpu (after all non-background subsystems have ran that tick)
-// SS_BACKGROUND has its own priority bracket
+/** Subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) */
+/// SS_BACKGROUND has its own priority bracket, this overrides SS_TICKER's priority bump
#define SS_BACKGROUND 4
//subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background))
#define SS_NO_TICK_CHECK 8
//Treat wait as a tick count, not DS, run every wait ticks.
-// (also forces it to run first in the tick, above even SS_NO_TICK_CHECK subsystems)
+/// (also forces it to run first in the tick (unless SS_BACKGROUND))
// (implies all runlevels because of how it works)
-// (overrides SS_BACKGROUND)
// This is designed for basically anything that works as a mini-mc (like SStimer)
#define SS_TICKER 16
diff --git a/code/__DEFINES/_spacemandmm.dm b/code/__DEFINES/_spacemandmm.dm
new file mode 100644
index 00000000000..ca54ca4b932
--- /dev/null
+++ b/code/__DEFINES/_spacemandmm.dm
@@ -0,0 +1,26 @@
+// This file contains all the defines related to the spacemanDMM linter (dreamchecker). When running under normal conditions, BYOND will ignore all these
+#ifdef SPACEMAN_DMM
+ #define RETURN_TYPE(X) set SpacemanDMM_return_type = X
+ #define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X
+ #define UNLINT(X) SpacemanDMM_unlint(X)
+ #define SHOULD_NOT_OVERRIDE(X) set SpacemanDMM_should_not_override = X
+ #define SHOULD_NOT_SLEEP(X)
+ #define SHOULD_BE_PURE(X)
+ #define PRIVATE_PROC(X)
+ #define PROTECTED_PROC(X)
+ #define VAR_FINAL var/SpacemanDMM_final
+ #define VAR_PRIVATE var
+ #define VAR_PROTECTED var
+#else
+ #define RETURN_TYPE(X)
+ #define SHOULD_CALL_PARENT(X)
+ #define UNLINT(X) X
+ #define SHOULD_NOT_OVERRIDE(X)
+ #define SHOULD_NOT_SLEEP(X)
+ #define SHOULD_BE_PURE(X)
+ #define PRIVATE_PROC(X)
+ #define PROTECTED_PROC(X)
+ #define VAR_FINAL var
+ #define VAR_PRIVATE var
+ #define VAR_PROTECTED var
+#endif
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index bbf394c6c0b..95494fb88cf 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -40,10 +40,11 @@
#define R_MOD 8192
#define R_MENTOR 16384
#define R_PROCCALL 32768
+#define R_VIEWRUNTIMES 65536
-#define R_MAXPERMISSION 32768 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+#define R_MAXPERMISSION 65536 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
-#define R_HOST 65535
+#define R_HOST 131071 // Sum of all permissions to allow easy setting
#define ADMIN_QUE(user,display) "[display]"
#define ADMIN_FLW(user,display) "[display]"
diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm
index c39ce0947de..1678ea69c8e 100644
--- a/code/__DEFINES/clothing.dm
+++ b/code/__DEFINES/clothing.dm
@@ -78,7 +78,7 @@
//flags for covering body parts
#define GLASSESCOVERSEYES 1
-#define MASKCOVERSEYES 2 // get rid of some of the other retardation in these flags
+#define MASKCOVERSEYES 2 // get rid of some of the other mess in these flags
#define HEADCOVERSEYES 4 // feel free to realloc these numbers for other purposes
#define MASKCOVERSMOUTH 8 // on other items, these are just for mask/head
#define HEADCOVERSMOUTH 16
@@ -92,8 +92,6 @@
#define BLOCKHEADHAIR 4 // temporarily removes the user's hair overlay. Leaves facial hair.
#define BLOCKHAIR 32768 // temporarily removes the user's hair, facial and otherwise.
-#define ONESIZEFITSALL 1 // determines if something can be worn by a fatty or not.
-
//flags for muzzle speech blocking
#define MUZZLE_MUTE_NONE 0 // Does not mute you.
#define MUZZLE_MUTE_MUFFLE 1 // Muffles everything you say "MHHPHHMMM!!!
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 956930aae70..2f98b6ee7b5 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -35,7 +35,6 @@
#define CANPUSH 8
#define PASSEMOTES 16 //Mob has a cortical borer or holders inside of it that need to see emotes.
#define GOTTAGOFAST 32
-#define GOTTAGOFAST_METH 64
#define IGNORESLOWDOWN 128
#define GODMODE 4096
#define FAKEDEATH 8192 //Replaces stuff like changeling.changeling_fakedeath
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
deleted file mode 100644
index c9691c195b8..00000000000
--- a/code/__DEFINES/components.dm
+++ /dev/null
@@ -1,291 +0,0 @@
-#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) )
-
-#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )
-
-//shorthand
-#define GET_COMPONENT_FROM(varname, path, target) var##path/##varname = ##target.GetComponent(##path)
-#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src)
-
-#define COMPONENT_INCOMPATIBLE 1
-
-// How multiple components of the exact same type are handled in the same datum
-
-#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
-#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
-#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
-#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new
-
-// All signals. Format:
-// When the signal is called: (signal arguments)
-// All signals send the source datum of the signal as the first argument
-
-// global signals
-// These are signals which can be listened to by any component on any parent
-// start global signals with "!", this used to be necessary but now it's just a formatting choice
-#define COMSIG_GLOB_NEW_Z "!new_z" //from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
-#define COMSIG_GLOB_VAR_EDIT "!var_edit" //called after a successful var edit somewhere in the world: (list/args)
-#define COMSIG_GLOB_MOB_CREATED "!mob_created" //mob was created somewhere : (mob)
-#define COMSIG_GLOB_MOB_DEATH "!mob_death" //mob died somewhere : (mob , gibbed)
-
-//////////////////////////////////////////////////////////////////
-
-// /datum signals
-#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component)
-#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component)
-#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
-#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
-#define COMSIG_TOPIC "handle_topic" //generic topic handler (usr, href_list)
-
-// /atom signals
-#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
- #define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
-#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
-#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob, result)
-#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides)
- //Positions for overrides list
- #define EXAMINE_POSITION_ARTICLE 1
- #define EXAMINE_POSITION_BEFORE 2
- //End positions
- #define COMPONENT_EXNAME_CHANGED 1
-#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom)
-#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
-#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
- #define COMPONENT_ATOM_BLOCK_EXIT 1
-#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
-#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)
-#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume)
-#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone)
-#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob)
-#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume)
-#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): ()
-#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity)
-#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): ()
-#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): ()
-#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
-#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
-#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color)
-#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir)
-#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted)
-#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities)
-#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): ()
- #define COMPONENT_BLOCK_RADIATION 1
-#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength)
- #define COMPONENT_BLOCK_CONTAMINATION 1
-#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
- #define COMPONENT_RAD_WAVE_HANDLED 1
-#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next)
- #define COMPONENT_BLOCK_REACH 1
-#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
-/////////////////
-#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost)
-#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user)
-#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" //from base of atom/attack_paw(): (mob/user)
- #define COMPONENT_NO_ATTACK_HAND 1 //works on all 3.
-/////////////////
-
-#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area)
-#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area)
-
-#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user)
-#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
-#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob)
-#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob)
-#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob)
-#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" //from base of atom/MouseDrop(): (/atom/over, /mob/user)
- #define COMPONENT_NO_MOUSEDROP 1
-#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" //from base of atom/MouseDrop_T: (/atom/from, /mob/user)
-
-// /area signals
-#define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M)
-#define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M)
-
-// /turf signals
-#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps)
-#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" //from base of atom/has_gravity(): (atom/asker, list/forced_gravities)
-
-// /atom/movable signals
-#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
-#define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable)
-#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
-#define COMSIG_CROSSED_MOVABLE "crossed_movable" //when we cross over something (calling Crossed() on that atom)
-#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable)
-#define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable)
- #define COMPONENT_MOVABLE_BLOCK_UNCROSS 1
-#define COMSIG_MOVABLE_BUMP "movable_bump" //from base of atom/movable/Bump(): (/atom)
-#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum)
-#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone)
-#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force)
-#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force)
-#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw" //from base of atom/movable/throw_at(): (list/args)
- #define COMPONENT_CANCEL_THROW 1
-#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin)
-#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z)
-#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
-#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
-
-// /mob signals
-#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
-#define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params)
- #define COMSIG_MOB_CANCEL_CLICKON 1
-#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
-#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources)
- #define COMPONENT_BLOCK_MAGIC 1
-#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): ()
-#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of
-#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //from base of /obj/item/attack(): (mob/M, mob/user)
-#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
-#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
-#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
-#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
-
-// /mob/living signals
-#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
-#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living)
-#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living)
-#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage)
-#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
-
-//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
-#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore)
-#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore)
-#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" //from base of mob/living/Paralyze() (amount, update, ignore)
-#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" //from base of mob/living/Immobilize() (amount, update, ignore)
-#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" //from base of mob/living/Unconscious() (amount, update, ignore)
-#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" //from base of mob/living/Sleeping() (amount, update, ignore)
- #define COMPONENT_NO_STUN 1 //For all of them
-
-// /mob/living/carbon signals
-#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
-
-// /mob/living/simple_animal/hostile signals
-#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
- #define COMPONENT_HOSTILE_NO_ATTACK 1
-
-// /obj signals
-#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
-#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
-#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon" //called in /obj/update_icon()
-
-
-// /obj/item signals
-#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
-#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
- #define COMPONENT_NO_INTERACT 1
-#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
- #define COMPONENT_NO_ATTACK_OBJ 1
-#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params)
- #define COMPONENT_NO_ATTACK 1
-#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params)
-#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot)
-#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user)
-#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker)
-#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
-#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
-#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args)
-
-// /obj/item/clothing signals
-#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
-
-// /obj/item/implant signals
-#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): ()
-#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" //from base of /obj/item/implant/proc/implant(): (list/args)
- #define COMPONENT_STOP_IMPLANTING 1
-#define COMSIG_IMPLANT_OTHER "implant_other" //called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant)
- //#define COMPONENT_STOP_IMPLANTING 1 //The name makes sense for both
- #define COMPONENT_DELETE_NEW_IMPLANT 2
- #define COMPONENT_DELETE_OLD_IMPLANT 4
-#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" //called on implants being implanted into someone with an uplink implant: (datum/component/uplink)
- //This uses all return values of COMSIG_IMPLANT_OTHER
-
-// /obj/item/pda signals
-#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" //called on pda when the user changes the ringtone: (mob/living/user, new_ringtone)
- #define COMPONENT_STOP_RINGTONE_CHANGE 1
-
-// /obj/item/radio signals
-#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" //called from base of /obj/item/radio/proc/set_frequency(): (list/args)
-
-// /obj/item/pen signals
-#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
-
-
-// /mob/living/carbon/human signals
-#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
-#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
-#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
-
-// /datum/species signals
-#define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species)
-#define COMSIG_SPECIES_LOSS "species_loss" //from datum/species/on_species_loss(): (datum/species/lost_species)
-
-/*******Component Specific Signals*******/
-//Janitor
-#define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values.
-#define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool.
-#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" //called on an object to clean it of cleanables. Usualy with soap: (num/strength)
-
-//Food
-#define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder)
-
-//Mood
-#define COMSIG_ADD_MOOD_EVENT "add_mood" //Called when you send a mood event from anywhere in the code.
-#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" //Called when you clear a mood event from anywhere in the code.
-
-//NTnet
-#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata))
-
-//Nanites
-#define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found
-#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" //(list/nanite_programs) - makes the input list a copy the nanites' program list
-#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" //(amount) Sets current nanite volume to the given amount
-#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" //(amount) Adjusts nanite volume by the given amount
-#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" //(amount) Sets maximum nanite volume to the given amount
-#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" //(amount(0-100)) Sets cloud ID to the given amount
-#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" //(amount) Sets safety threshold to the given amount
-#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" //(amount) Sets regeneration rate to the given amount
-#define COMSIG_NANITE_SIGNAL "nanite_signal" //(code(1-9999)) Called when sending a nanite signal to a mob.
-#define COMSIG_NANITE_SCAN "nanite_scan" //(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected
-#define COMSIG_NANITE_UI_DATA "nanite_ui_data" //(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs
-#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" //(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component
- #define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful
- #define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites
-#define COMSIG_NANITE_SYNC "nanite_sync" //(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component
-
-// /datum/component/storage signals
-#define COMSIG_CONTAINS_STORAGE "is_storage" //() - returns bool.
-#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert" //(obj/item/inserting, mob/user, silent, force) - returns bool
-#define COMSIG_TRY_STORAGE_SHOW "storage_show_to" //(mob/show_to, force) - returns bool.
-#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from" //(mob/hide_from) - returns bool
-#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all" //returns bool
-#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state" //(newstate)
-#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate" //() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST!
-#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type" //(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types.
-#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" //(type, amount = INFINITY, force = FALSE) //don't fuck this up. Force will ignore max_items, and amount is normally clamped to max_items.
-#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" //(obj, new_loc, force = FALSE) - returns bool
-#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" //(loc) - returns bool - if loc is null it will dump at parent location.
-#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE)
-#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" //(obj/item/insertion_candidate, mob/user, silent) - returns bool
-
-// /datum/action signals
-#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action)
- #define COMPONENT_ACTION_BLOCK_TRIGGER 1
-
-/*******Non-Signal Component Related Defines*******/
-
-//Redirection component init flags
-#define REDIRECT_TRANSFER_WITH_TURF 1
-
-//Arch
-#define ARCH_PROB "probability" //Probability for each item
-#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount
-
-//Ouch my toes!
-#define CALTROP_BYPASS_SHOES 1
-#define CALTROP_IGNORE_WALKERS 2
-
-//Xenobio hotkeys
-#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob)
-#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob)
-#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob)
-#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob)
-#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob)
-#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob)
diff --git a/code/__DEFINES/criminal_status.dm b/code/__DEFINES/criminal_status.dm
new file mode 100644
index 00000000000..75c33909fc2
--- /dev/null
+++ b/code/__DEFINES/criminal_status.dm
@@ -0,0 +1,10 @@
+//criminal status defines
+#define SEC_RECORD_STATUS_NONE "None"
+#define SEC_RECORD_STATUS_ARREST "*Arrest*"
+#define SEC_RECORD_STATUS_EXECUTE "*Execute*"
+#define SEC_RECORD_STATUS_INCARCERATED "Incarcerated"
+#define SEC_RECORD_STATUS_RELEASED "Released"
+#define SEC_RECORD_STATUS_PAROLLED "Parolled"
+#define SEC_RECORD_STATUS_DEMOTE "Demote"
+#define SEC_RECORD_STATUS_SEARCH "Search"
+#define SEC_RECORD_STATUS_MONITOR "Monitor"
diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm
new file mode 100644
index 00000000000..128c9f19387
--- /dev/null
+++ b/code/__DEFINES/dcs/flags.dm
@@ -0,0 +1,41 @@
+/// Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type.
+/// `parent` must not be modified if this is to be returned.
+/// This will be noted in the runtime logs
+#define COMPONENT_INCOMPATIBLE 1
+/// Returned in PostTransfer to prevent transfer, similar to `COMPONENT_INCOMPATIBLE`
+#define COMPONENT_NOTRANSFER 2
+
+/// Return value to cancel attaching
+#define ELEMENT_INCOMPATIBLE 1
+
+// /datum/element flags
+/// Causes the detach proc to be called when the host object is being deleted
+#define ELEMENT_DETACH (1 << 0)
+/**
+ * Only elements created with the same arguments given after `id_arg_index` share an element instance
+ * The arguments are the same when the text and number values are the same and all other values have the same ref
+ */
+#define ELEMENT_BESPOKE (1 << 1)
+
+// How multiple components of the exact same type are handled in the same datum
+/// old component is deleted (default)
+#define COMPONENT_DUPE_HIGHLANDER 0
+/// duplicates allowed
+#define COMPONENT_DUPE_ALLOWED 1
+/// new component is deleted
+#define COMPONENT_DUPE_UNIQUE 2
+/// old component is given the initialization args of the new
+#define COMPONENT_DUPE_UNIQUE_PASSARGS 4
+/// each component of the same type is consulted as to whether the duplicate should be allowed
+#define COMPONENT_DUPE_SELECTIVE 5
+
+//Redirection component init flags
+#define REDIRECT_TRANSFER_WITH_TURF 1
+
+//Arch
+#define ARCH_PROB "probability" //Probability for each item
+#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount
+
+//Ouch my toes!
+#define CALTROP_BYPASS_SHOES 1
+#define CALTROP_IGNORE_WALKERS 2
diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm
new file mode 100644
index 00000000000..144e94f1fe0
--- /dev/null
+++ b/code/__DEFINES/dcs/helpers.dm
@@ -0,0 +1,15 @@
+/// Used to trigger signals and call procs registered for that signal
+/// The datum hosting the signal is automaticaly added as the first argument
+/// Returns a bitfield gathered from all registered procs
+/// Arguments given here are packaged in a list and given to _SendSignal
+#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) )
+
+#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )
+
+/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments
+#define AddElement(arguments...) _AddElement(list(##arguments))
+/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments
+#define RemoveElement(arguments...) _RemoveElement(list(##arguments))
+
+/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments
+#define AddComponent(arguments...) _AddComponent(list(##arguments))
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
new file mode 100644
index 00000000000..10aa1718dda
--- /dev/null
+++ b/code/__DEFINES/dcs/signals.dm
@@ -0,0 +1,728 @@
+// All signals. Format:
+// When the signal is called: (signal arguments)
+// All signals send the source datum of the signal as the first argument
+
+// global signals
+// These are signals which can be listened to by any component on any parent
+// start global signals with "!", this used to be necessary but now it's just a formatting choice
+
+///from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
+#define COMSIG_GLOB_NEW_Z "!new_z"
+/// called after a successful var edit somewhere in the world: (list/args)
+#define COMSIG_GLOB_VAR_EDIT "!var_edit"
+/// called after an explosion happened : (epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
+#define COMSIG_GLOB_EXPLOSION "!explosion"
+/// mob was created somewhere : (mob)
+#define COMSIG_GLOB_MOB_CREATED "!mob_created"
+/// mob died somewhere : (mob , gibbed)
+#define COMSIG_GLOB_MOB_DEATH "!mob_death"
+/// global living say plug - use sparingly: (mob/speaker , message)
+#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special"
+/// called by datum/cinematic/play() : (datum/cinematic/new_cinematic)
+#define COMSIG_GLOB_PLAY_CINEMATIC "!play_cinematic"
+ #define COMPONENT_GLOB_BLOCK_CINEMATIC (1<<0)
+/// ingame button pressed (/obj/machinery/button/button)
+#define COMSIG_GLOB_BUTTON_PRESSED "!button_pressed"
+
+/// signals from globally accessible objects
+
+///from SSsun when the sun changes position : (azimuth)
+#define COMSIG_SUN_MOVED "sun_moved"
+
+//////////////////////////////////////////////////////////////////
+
+// /datum signals
+/// when a component is added to a datum: (/datum/component)
+#define COMSIG_COMPONENT_ADDED "component_added"
+/// before a component is removed from a datum because of RemoveComponent: (/datum/component)
+#define COMSIG_COMPONENT_REMOVING "component_removing"
+/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
+#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted"
+/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
+#define COMSIG_PARENT_QDELETING "parent_qdeleting"
+/// generic topic handler (usr, href_list)
+#define COMSIG_TOPIC "handle_topic"
+
+/// fires on the target datum when an element is attached to it (/datum/element)
+#define COMSIG_ELEMENT_ATTACH "element_attach"
+/// fires on the target datum when an element is attached to it (/datum/element)
+#define COMSIG_ELEMENT_DETACH "element_detach"
+
+// /atom signals
+///from base of atom/proc/Initialize(): sent any time a new atom is created
+#define COMSIG_ATOM_CREATED "atom_created"
+//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization
+#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success"
+///from base of atom/attackby(): (/obj/item, /mob/living, params)
+#define COMSIG_PARENT_ATTACKBY "atom_attackby"
+///Return this in response if you don't want afterattack to be called
+ #define COMPONENT_NO_AFTERATTACK (1<<0)
+///from base of atom/attack_hulk(): (/mob/living/carbon/human)
+#define COMSIG_ATOM_HULK_ATTACK "hulk_attack"
+///from base of atom/animal_attack(): (/mob/user)
+#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal"
+///from base of atom/examine(): (/mob)
+#define COMSIG_PARENT_EXAMINE "atom_examine"
+///from base of atom/get_examine_name(): (/mob, list/overrides)
+#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name"
+ //Positions for overrides list
+ #define EXAMINE_POSITION_ARTICLE (1<<0)
+ #define EXAMINE_POSITION_BEFORE (1<<1)
+ //End positions
+ #define COMPONENT_EXNAME_CHANGED (1<<0)
+///from base of atom/update_icon(): ()
+#define COMSIG_ATOM_UPDATE_ICON "atom_update_icon"
+ #define COMSIG_ATOM_NO_UPDATE_ICON_STATE (1<<0)
+ #define COMSIG_ATOM_NO_UPDATE_OVERLAYS (1<<1)
+///from base of atom/update_overlays(): (list/new_overlays)
+#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays"
+///from base of atom/update_icon(): (signalOut, did_anything)
+#define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon"
+///from base of atom/Entered(): (atom/movable/entering, /atom)
+#define COMSIG_ATOM_ENTERED "atom_entered"
+///from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
+#define COMSIG_ATOM_EXIT "atom_exit"
+ #define COMPONENT_ATOM_BLOCK_EXIT (1<<0)
+///from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
+#define COMSIG_ATOM_EXITED "atom_exited"
+///from base of atom/Bumped(): (/atom/movable)
+#define COMSIG_ATOM_BUMPED "atom_bumped"
+///from base of atom/ex_act(): (severity, target)
+#define COMSIG_ATOM_EX_ACT "atom_ex_act"
+///from base of atom/emp_act(): (severity)
+#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
+///from base of atom/fire_act(): (exposed_temperature, exposed_volume)
+#define COMSIG_ATOM_FIRE_ACT "atom_fire_act"
+///from base of atom/bullet_act(): (/obj/projectile, def_zone)
+#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act"
+///from base of atom/blob_act(): (/obj/structure/blob)
+#define COMSIG_ATOM_BLOB_ACT "atom_blob_act"
+///from base of atom/acid_act(): (acidpwr, acid_volume)
+#define COMSIG_ATOM_ACID_ACT "atom_acid_act"
+///from base of atom/emag_act(): (/mob/user)
+#define COMSIG_ATOM_EMAG_ACT "atom_emag_act"
+///from base of atom/rad_act(intensity)
+#define COMSIG_ATOM_RAD_ACT "atom_rad_act"
+///from base of atom/narsie_act(): ()
+#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act"
+///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
+#define COMSIG_ATOM_RCD_ACT "atom_rcd_act"
+///from base of atom/singularity_pull(): (S, current_size)
+#define COMSIG_ATOM_SING_PULL "atom_sing_pull"
+///from obj/machinery/bsa/full/proc/fire(): ()
+#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass"
+ #define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0)
+///from base of atom/set_light(): (l_range, l_power, l_color)
+#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
+///from base of atom/setDir(): (old_dir, new_dir)
+#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
+///from base of atom/handle_atom_del(): (atom/deleted)
+#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del"
+///from base of atom/has_gravity(): (turf/location, list/forced_gravities)
+#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity"
+///from proc/get_rad_contents(): ()
+#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe"
+ #define COMPONENT_BLOCK_RADIATION (1<<0)
+///from base of datum/radiation_wave/radiate(): (strength)
+#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam"
+ #define COMPONENT_BLOCK_CONTAMINATION (1<<0)
+///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
+#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass"
+ #define COMPONENT_RAD_WAVE_HANDLED (1<<0)
+///from internal loop in atom/movable/proc/CanReach(): (list/next)
+#define COMSIG_ATOM_CANREACH "atom_can_reach"
+ #define COMPONENT_BLOCK_REACH (1<<0)
+///from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act"
+///from base of atom/wrench_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_WRENCH_ACT "atom_wrench_act"
+///from base of atom/multitool_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_MULTITOOL_ACT "atom_multitool_act"
+///from base of atom/welder_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_WELDER_ACT "atom_welder_act"
+///from base of atom/wirecutter_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_WIRECUTTER_ACT "atom_wirecutter_act"
+///from base of atom/crowbar_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_CROWBAR_ACT "atom_crowbar_act"
+///from base of atom/analyser_act(): (mob/living/user, obj/item/I)
+#define COMSIG_ATOM_ANALYSER_ACT "atom_analyser_act"
+ #define COMPONENT_BLOCK_TOOL_ATTACK (1<<0)
+///called when teleporting into a protected turf: (channel, turf/origin)
+#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport"
+ #define COMPONENT_BLOCK_TELEPORT (1<<0)
+///called when an atom is added to the hearers on get_hearers_in_view(): (list/processing_list, list/hearers)
+#define COMSIG_ATOM_HEARER_IN_VIEW "atom_hearer_in_view"
+///called when an atom starts orbiting another atom: (atom)
+#define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin"
+///called when an atom stops orbiting another atom: (atom)
+#define COMSIG_ATOM_ORBIT_STOP "atom_orbit_stop"
+/////////////////
+///from base of atom/attack_ghost(): (mob/dead/observer/ghost)
+#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost"
+///from base of atom/attack_hand(): (mob/user)
+#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
+///from base of atom/attack_paw(): (mob/user)
+#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw"
+ #define COMPONENT_NO_ATTACK_HAND (1<<0) //works on all 3.
+//This signal return value bitflags can be found in __DEFINES/misc.dm
+
+///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
+#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
+///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force)
+#define COMSIG_ATOM_START_PULL "movable_start_pull"
+///called on /living when someone starts pulling it (atom/movable/puller, state, force)
+#define COMSIG_LIVING_START_PULL "living_start_pull"
+
+/////////////////
+
+///from base of area/Entered(): (/area)
+#define COMSIG_ENTER_AREA "enter_area"
+///from base of area/Exited(): (/area)
+#define COMSIG_EXIT_AREA "exit_area"
+///from base of atom/Click(): (location, control, params, mob/user)
+#define COMSIG_CLICK "atom_click"
+///from base of atom/ShiftClick(): (/mob)
+#define COMSIG_CLICK_SHIFT "shift_click"
+ #define COMPONENT_ALLOW_EXAMINATE (1<<0) //Allows the user to examinate regardless of client.eye.
+///from base of atom/CtrlClickOn(): (/mob)
+#define COMSIG_CLICK_CTRL "ctrl_click"
+///from base of atom/AltClick(): (/mob)
+#define COMSIG_CLICK_ALT "alt_click"
+///from base of atom/CtrlShiftClick(/mob)
+#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click"
+///from base of atom/MouseDrop(): (/atom/over, /mob/user)
+#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto"
+ #define COMPONENT_NO_MOUSEDROP (1<<0)
+///from base of atom/MouseDrop_T: (/atom/from, /mob/user)
+#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto"
+
+// /area signals
+
+///from base of area/Entered(): (atom/movable/M)
+#define COMSIG_AREA_ENTERED "area_entered"
+///from base of area/Exited(): (atom/movable/M)
+#define COMSIG_AREA_EXITED "area_exited"
+
+// /turf signals
+
+///from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps)
+#define COMSIG_TURF_CHANGE "turf_change"
+///from base of atom/has_gravity(): (atom/asker, list/forced_gravities)
+#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity"
+///from base of turf/New(): (turf/source, direction)
+#define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new"
+
+// /atom/movable signals
+
+///from base of atom/movable/Moved(): (/atom)
+#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move"
+ #define COMPONENT_MOVABLE_BLOCK_PRE_MOVE (1<<0)
+///from base of atom/movable/Moved(): (/atom, dir)
+#define COMSIG_MOVABLE_MOVED "movable_moved"
+///from base of atom/movable/Cross(): (/atom/movable)
+#define COMSIG_MOVABLE_CROSS "movable_cross"
+///from base of atom/movable/Crossed(): (/atom/movable)
+#define COMSIG_MOVABLE_CROSSED "movable_crossed"
+///when we cross over something (calling Crossed() on that atom)
+#define COMSIG_CROSSED_MOVABLE "crossed_movable"
+///from base of atom/movable/Uncross(): (/atom/movable)
+#define COMSIG_MOVABLE_UNCROSS "movable_uncross"
+ #define COMPONENT_MOVABLE_BLOCK_UNCROSS (1<<0)
+///from base of atom/movable/Uncrossed(): (/atom/movable)
+#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed"
+///from base of atom/movable/Bump(): (/atom)
+#define COMSIG_MOVABLE_BUMP "movable_bump"
+///from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum)
+#define COMSIG_MOVABLE_IMPACT "movable_impact"
+ #define COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH (1<<0) //if true, flip if the impact will push what it hits
+ #define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on
+///from base of mob/living/hitby(): (mob/living/target, hit_zone)
+#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone"
+///from base of atom/movable/buckle_mob(): (mob, force)
+#define COMSIG_MOVABLE_BUCKLE "buckle"
+///from base of atom/movable/unbuckle_mob(): (mob, force)
+#define COMSIG_MOVABLE_UNBUCKLE "unbuckle"
+///from base of atom/movable/throw_at(): (list/args)
+#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw"
+ #define COMPONENT_CANCEL_THROW (1<<0)
+///from base of atom/movable/throw_at(): (datum/thrownthing, spin)
+#define COMSIG_MOVABLE_POST_THROW "movable_post_throw"
+///from base of atom/movable/onTransitZ(): (old_z, new_z)
+#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit"
+///called when the movable is placed in an unaccessible area, used for stationloving: ()
+#define COMSIG_MOVABLE_SECLUDED_LOCATION "movable_secluded"
+///from base of atom/movable/Hear(): (proc args list(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode))
+#define COMSIG_MOVABLE_HEAR "movable_hear"
+ #define HEARING_MESSAGE 1
+ #define HEARING_SPEAKER 2
+// #define HEARING_LANGUAGE 3
+ #define HEARING_RAW_MESSAGE 4
+ /* #define HEARING_RADIO_FREQ 5
+ #define HEARING_SPANS 6
+ #define HEARING_MESSAGE_MODE 7 */
+
+///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
+#define COMSIG_MOVABLE_DISPOSING "movable_disposing"
+
+// /mob signals
+
+///from base of /mob/Login(): ()
+#define COMSIG_MOB_LOGIN "mob_login"
+///from base of /mob/Logout(): ()
+#define COMSIG_MOB_LOGOUT "mob_logout"
+///from base of mob/death(): (gibbed)
+#define COMSIG_MOB_DEATH "mob_death"
+///from base of mob/set_stat(): (new_stat)
+#define COMSIG_MOB_STATCHANGE "mob_statchange"
+///from base of mob/clickon(): (atom/A, params)
+#define COMSIG_MOB_CLICKON "mob_clickon"
+///from base of mob/MiddleClickOn(): (atom/A)
+#define COMSIG_MOB_MIDDLECLICKON "mob_middleclickon"
+///from base of mob/AltClickOn(): (atom/A)
+#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
+ #define COMSIG_MOB_CANCEL_CLICKON (1<<0)
+
+///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
+#define COMSIG_MOB_ALLOWED "mob_allowed"
+///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
+#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic"
+ #define COMPONENT_BLOCK_MAGIC (1<<0)
+///from base of mob/create_mob_hud(): ()
+#define COMSIG_MOB_HUD_CREATED "mob_hud_created"
+///from base of atom/attack_hand(): (mob/user)
+#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand"
+///from base of /obj/item/attack(): (mob/M, mob/user)
+#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack"
+ #define COMPONENT_ITEM_NO_ATTACK (1<<0)
+///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone)
+#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage"
+///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
+#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack"
+///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters)
+#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted"
+///from base of mob/RangedAttack(): (atom/A, params)
+#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged"
+///from base of /mob/throw_item(): (atom/target)
+#define COMSIG_MOB_THROW "mob_throw"
+///from base of /mob/verb/examinate(): (atom/target)
+#define COMSIG_MOB_EXAMINATE "mob_examinate"
+///from base of /mob/update_sight(): ()
+#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight"
+////from /mob/living/say(): ()
+#define COMSIG_MOB_SAY "mob_say"
+ #define COMPONENT_UPPERCASE_SPEECH (1<<0)
+ // used to access COMSIG_MOB_SAY argslist
+ #define SPEECH_MESSAGE 1
+ // #define SPEECH_BUBBLE_TYPE 2
+ #define SPEECH_SPANS 3
+ /* #define SPEECH_SANITIZE 4
+ #define SPEECH_LANGUAGE 5
+ #define SPEECH_IGNORE_SPAM 6
+ #define SPEECH_FORCED 7 */
+
+///from /mob/say_dead(): (mob/speaker, message)
+#define COMSIG_MOB_DEADSAY "mob_deadsay"
+ #define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0)
+///from /mob/living/emote(): ()
+#define COMSIG_MOB_EMOTE "mob_emote"
+///from base of mob/swap_hand(): (obj/item)
+#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands"
+ #define COMPONENT_BLOCK_SWAP (1<<0)
+
+// /mob/living signals
+
+///from base of mob/living/resist() (/mob/living)
+#define COMSIG_LIVING_RESIST "living_resist"
+///from base of mob/living/IgniteMob() (/mob/living)
+#define COMSIG_LIVING_IGNITED "living_ignite"
+///from base of mob/living/ExtinguishMob() (/mob/living)
+#define COMSIG_LIVING_EXTINGUISHED "living_extinguished"
+///from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags)
+#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act"
+///sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check)
+#define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented"
+///sent by stuff like stunbatons and tasers: ()
+#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock"
+///from base of mob/living/revive() (full_heal, admin_revive)
+#define COMSIG_LIVING_REVIVE "living_revive"
+///from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
+#define COMSIG_LIVING_REGENERATE_LIMBS "living_regen_limbs"
+///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment
+#define COMSIG_LIVING_ATTACH_LIMB "living_attach_limb"
+ #define COMPONENT_NO_ATTACH (1<<0)
+///sent from borg recharge stations: (amount, repairs)
+#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge"
+///sent when a mob/login() finishes: (client)
+#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login"
+///sent from borg mobs to itself, for tools to catch an upcoming destroy() due to safe decon (rather than detonation)
+#define COMSIG_BORG_SAFE_DECONSTRUCT "borg_safe_decon"
+
+//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
+
+///from base of mob/living/Stun() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_STUN "living_stun"
+///from base of mob/living/Knockdown() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown"
+///from base of mob/living/Paralyze() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze"
+///from base of mob/living/Immobilize() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize"
+///from base of mob/living/Unconscious() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious"
+///from base of mob/living/Sleeping() (amount, update, ignore)
+#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping"
+ #define COMPONENT_NO_STUN (1<<0) //For all of them
+///from base of /mob/living/can_track(): (mob/user)
+#define COMSIG_LIVING_CAN_TRACK "mob_cantrack"
+ #define COMPONENT_CANT_TRACK (1<<0)
+
+// /mob/living/carbon signals
+
+///from base of mob/living/carbon/soundbang_act(): (list(intensity))
+#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang"
+///from /item/organ/proc/Insert() (/obj/item/organ/)
+#define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ"
+///from /item/organ/proc/Remove() (/obj/item/organ/)
+#define COMSIG_CARBON_LOSE_ORGAN "carbon_lose_organ"
+///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent)
+#define COMSIG_CARBON_EQUIP_HAT "carbon_equip_hat"
+///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent)
+#define COMSIG_CARBON_UNEQUIP_HAT "carbon_unequip_hat"
+///defined twice, in carbon and human's topics, fired when interacting with a valid embedded_object to pull it out (mob/living/carbon/target, /obj/item, /obj/item/bodypart/L)
+#define COMSIG_CARBON_EMBED_RIP "item_embed_start_rip"
+///called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item)
+#define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe"
+
+// /mob/living/simple_animal/hostile signals
+#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
+ #define COMPONENT_HOSTILE_NO_ATTACK (1<<0)
+
+// /obj signals
+
+///from base of obj/deconstruct(): (disassembled)
+#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct"
+///called in /obj/structure/setAnchored(): (value)
+#define COMSIG_OBJ_SETANCHORED "obj_setanchored"
+///from base of code/game/machinery
+#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench"
+///from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide
+#define COMSIG_OBJ_HIDE "obj_hide"
+///called in /obj/update_icon()
+#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon"
+
+// /obj/machinery signals
+
+///from /obj/machinery/obj_break(damage_flag): (damage_flag)
+#define COMSIG_MACHINERY_BROKEN "machinery_broken"
+///from base power_change() when power is lost
+#define COMSIG_MACHINERY_POWER_LOST "machinery_power_lost"
+///from base power_change() when power is restored
+#define COMSIG_MACHINERY_POWER_RESTORED "machinery_power_restored"
+
+// /obj/item signals
+
+///from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
+#define COMSIG_ITEM_ATTACK "item_attack"
+///from base of obj/item/attack_self(): (/mob)
+#define COMSIG_ITEM_ATTACK_SELF "item_attack_self"
+ #define COMPONENT_NO_INTERACT (1<<0)
+///from base of obj/item/attack_obj(): (/obj, /mob)
+#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj"
+ #define COMPONENT_NO_ATTACK_OBJ (1<<0)
+///from base of obj/item/pre_attack(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack"
+ #define COMPONENT_NO_ATTACK (1<<0)
+///from base of obj/item/afterattack(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_AFTERATTACK "item_afterattack"
+///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params)
+#define COMSIG_ITEM_ATTACK_QDELETED "item_attack_qdeleted"
+///from base of obj/item/equipped(): (/mob/equipper, slot)
+#define COMSIG_ITEM_EQUIPPED "item_equip"
+///from base of obj/item/dropped(): (mob/user)
+#define COMSIG_ITEM_DROPPED "item_drop"
+///from base of obj/item/pickup(): (/mob/taker)
+#define COMSIG_ITEM_PICKUP "item_pickup"
+///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
+#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone"
+///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
+#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul"
+///called before marking an object for retrieval, checked in /obj/effect/proc_holder/spell/targeted/summonitem/cast() : (mob/user)
+#define COMSIG_ITEM_MARK_RETRIEVAL "item_mark_retrieval"
+ #define COMPONENT_BLOCK_MARK_RETRIEVAL (1<<0)
+///from base of obj/item/hit_reaction(): (list/args)
+#define COMSIG_ITEM_HIT_REACT "item_hit_react"
+///called on item when crossed by something (): (/atom/movable, mob/living/crossed)
+#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed"
+///called on item when microwaved (): (obj/machinery/microwave/M)
+#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act"
+///from base of item/sharpener/attackby(): (amount, max)
+#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act"
+ #define COMPONENT_BLOCK_SHARPEN_APPLIED (1<<0)
+ #define COMPONENT_BLOCK_SHARPEN_BLOCKED (1<<1)
+ #define COMPONENT_BLOCK_SHARPEN_ALREADY (1<<2)
+ #define COMPONENT_BLOCK_SHARPEN_MAXED (1<<3)
+///from base of [/obj/item/proc/tool_check_callback]: (mob/living/user)
+#define COMSIG_TOOL_IN_USE "tool_in_use"
+///from base of [/obj/item/proc/tool_start_check]: (mob/living/user)
+#define COMSIG_TOOL_START_USE "tool_start_use"
+///from [/obj/item/proc/disableEmbedding]:
+#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed"
+///from [/obj/effect/mine/proc/triggermine]:
+#define COMSIG_MINE_TRIGGERED "minegoboom"
+
+// /obj/item signals for economy
+///called when an item is sold by the exports subsystem
+#define COMSIG_ITEM_SOLD "item_sold"
+///called when a wrapped up structure is opened by hand
+#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped"
+#define COMSIG_ITEM_UNWRAPPED "item_unwrapped"
+///called when a wrapped up item is opened by hand
+ #define COMSIG_ITEM_SPLIT_VALUE (1<<0)
+///called when getting the item's exact ratio for cargo's profit.
+#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits"
+///called when getting the item's exact ratio for cargo's profit, without selling the item.
+#define COMSIG_ITEM_SPLIT_PROFIT_DRY "item_split_profits_dry"
+
+// /obj/item/clothing signals
+
+///from base of obj/item/clothing/shoes/proc/step_action(): ()
+#define COMSIG_SHOES_STEP_ACTION "shoes_step_action"
+///from base of /obj/item/clothing/suit/space/proc/toggle_spacesuit(): (obj/item/clothing/suit/space/suit)
+#define COMSIG_SUIT_SPACE_TOGGLE "suit_space_toggle"
+
+// /obj/item/implant signals
+///from base of /obj/item/implant/proc/activate(): ()
+#define COMSIG_IMPLANT_ACTIVATED "implant_activated"
+///from base of /obj/item/implant/proc/implant(): (list/args)
+#define COMSIG_IMPLANT_IMPLANTING "implant_implanting"
+ #define COMPONENT_STOP_IMPLANTING (1<<0)
+///called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant)
+#define COMSIG_IMPLANT_OTHER "implant_other"
+ //#define COMPONENT_STOP_IMPLANTING (1<<0) //The name makes sense for both
+ #define COMPONENT_DELETE_NEW_IMPLANT (1<<1)
+ #define COMPONENT_DELETE_OLD_IMPLANT (1<<2)
+///called on implants being implanted into someone with an uplink implant: (datum/component/uplink)
+#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists"
+ //This uses all return values of COMSIG_IMPLANT_OTHER
+
+// /obj/item/pda signals
+
+///called on pda when the user changes the ringtone: (mob/living/user, new_ringtone)
+#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone"
+ #define COMPONENT_STOP_RINGTONE_CHANGE (1<<0)
+#define COMSIG_PDA_CHECK_DETONATE "pda_check_detonate"
+ #define COMPONENT_PDA_NO_DETONATE (1<<0)
+
+// /obj/item/radio signals
+
+///called from base of /obj/item/radio/proc/set_frequency(): (list/args)
+#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency"
+
+// /obj/item/pen signals
+
+///called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
+#define COMSIG_PEN_ROTATED "pen_rotated"
+
+// /obj/item/gun signals
+
+///called in /obj/item/gun/process_fire (user, target, params, zone_override)
+#define COMSIG_MOB_FIRED_GUN "mob_fired_gun"
+
+// /obj/item/grenade signals
+
+///called in /obj/item/gun/process_fire (user, target, params, zone_override)
+#define COMSIG_GRENADE_PRIME "grenade_prime"
+///called in /obj/item/gun/process_fire (user, target, params, zone_override)
+#define COMSIG_GRENADE_ARMED "grenade_armed"
+
+// /obj/projectile signals (sent to the firer)
+
+///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
+#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit"
+///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
+#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit"
+///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target)
+#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire"
+///from the base of /obj/projectile/proc/fire(): ()
+#define COMSIG_PROJECTILE_FIRE "projectile_fire"
+///sent to targets during the process_hit proc of projectiles
+#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit"
+///sent to targets during the process_hit proc of projectiles
+#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out"
+///sent when trying to force an embed (mainly for projectiles, only used in the embed element)
+#define COMSIG_EMBED_TRY_FORCE "item_try_embed"
+
+///sent to targets during the process_hit proc of projectiles
+#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init"
+
+// /obj/mecha signals
+
+///sent from mecha action buttons to the mecha they're linked to
+#define COMSIG_MECHA_ACTION_ACTIVATE "mecha_action_activate"
+
+// /mob/living/carbon/human signals
+
+///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
+#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
+///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
+#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack"
+///from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
+#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby"
+///Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
+#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit"
+///Whenever EquipRanked is called, called after job is set
+#define COMSIG_JOB_RECEIVED "job_received"
+
+// /datum/species signals
+
+///from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species)
+#define COMSIG_SPECIES_GAIN "species_gain"
+///from datum/species/on_species_loss(): (datum/species/lost_species)
+#define COMSIG_SPECIES_LOSS "species_loss"
+
+// /datum/song signals
+
+///sent to the instrument when a song starts playing
+#define COMSIG_SONG_START "song_start"
+///sent to the instrument when a song stops playing
+#define COMSIG_SONG_END "song_end"
+
+/*******Component Specific Signals*******/
+//Janitor
+
+///(): Returns bitflags of wet values.
+#define COMSIG_TURF_IS_WET "check_turf_wet"
+///(max_strength, immediate, duration_decrease = INFINITY): Returns bool.
+#define COMSIG_TURF_MAKE_DRY "make_turf_try"
+///called on an object to clean it of cleanables. Usualy with soap: (num/strength)
+#define COMSIG_COMPONENT_CLEAN_ACT "clean_act"
+
+//Creamed
+
+///called when you wash your face at a sink: (num/strength)
+#define COMSIG_COMPONENT_CLEAN_FACE_ACT "clean_face_act"
+
+//Food
+
+///from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder)
+#define COMSIG_FOOD_EATEN "food_eaten"
+
+//Gibs
+
+///from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases)
+#define COMSIG_GIBS_STREAK "gibs_streak"
+
+//Mood
+
+///called when you send a mood event from anywhere in the code.
+#define COMSIG_ADD_MOOD_EVENT "add_mood"
+///Mood event that only RnD members listen for
+#define COMSIG_ADD_MOOD_EVENT_RND "RND_add_mood"
+///called when you clear a mood event from anywhere in the code.
+#define COMSIG_CLEAR_MOOD_EVENT "clear_mood"
+
+//NTnet
+
+///called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata))
+#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive"
+
+//Nanites
+
+///() returns TRUE if nanites are found
+#define COMSIG_HAS_NANITES "has_nanites"
+///() returns TRUE if nanites have stealth
+#define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy"
+///() deletes the nanite component
+#define COMSIG_NANITE_DELETE "nanite_delete"
+///(list/nanite_programs) - makes the input list a copy the nanites' program list
+#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs"
+///(amount) Returns nanite amount
+#define COMSIG_NANITE_GET_VOLUME "nanite_get_volume"
+///(amount) Sets current nanite volume to the given amount
+#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume"
+///(amount) Adjusts nanite volume by the given amount
+#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust"
+///(amount) Sets maximum nanite volume to the given amount
+#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume"
+///(amount(0-100)) Sets cloud ID to the given amount
+#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud"
+///(method) Modify cloud sync status. Method can be toggle, enable or disable
+#define COMSIG_NANITE_SET_CLOUD_SYNC "nanite_set_cloud_sync"
+///(amount) Sets safety threshold to the given amount
+#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety"
+///(amount) Sets regeneration rate to the given amount
+#define COMSIG_NANITE_SET_REGEN "nanite_set_regen"
+///(code(1-9999)) Called when sending a nanite signal to a mob.
+#define COMSIG_NANITE_SIGNAL "nanite_signal"
+///(comm_code(1-9999), comm_message) Called when sending a nanite comm signal to a mob.
+#define COMSIG_NANITE_COMM_SIGNAL "nanite_comm_signal"
+///(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected
+#define COMSIG_NANITE_SCAN "nanite_scan"
+///(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs
+#define COMSIG_NANITE_UI_DATA "nanite_ui_data"
+///(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component
+#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program"
+ ///Installation successful
+ #define COMPONENT_PROGRAM_INSTALLED (1<<0)
+ ///Installation failed, but there are still nanites
+ #define COMPONENT_PROGRAM_NOT_INSTALLED (1<<1)
+///(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component
+#define COMSIG_NANITE_SYNC "nanite_sync"
+
+// /datum/component/storage signals
+
+///() - returns bool.
+#define COMSIG_CONTAINS_STORAGE "is_storage"
+///(obj/item/inserting, mob/user, silent, force) - returns bool
+#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert"
+///(mob/show_to, force) - returns bool.
+#define COMSIG_TRY_STORAGE_SHOW "storage_show_to"
+///(mob/hide_from) - returns bool
+#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from"
+///returns bool
+#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all"
+///(newstate)
+#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state"
+///() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST!
+#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate"
+///(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types.
+#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type"
+///(type, amount = INFINITY, force = FALSE). Force will ignore max_items, and amount is normally clamped to max_items.
+#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type"
+///(obj, new_loc, force = FALSE) - returns bool
+#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj"
+///(loc) - returns bool - if loc is null it will dump at parent location.
+#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty"
+///(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE)
+#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory"
+///(obj/item/insertion_candidate, mob/user, silent) - returns bool
+#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip"
+
+// /datum/component/two_handed signals
+
+///from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user)
+#define COMSIG_TWOHANDED_WIELD "twohanded_wield"
+ #define COMPONENT_TWOHANDED_BLOCK_WIELD (1<<0)
+///from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user)
+#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield"
+
+// /datum/action signals
+
+///from base of datum/action/proc/Trigger(): (datum/action)
+#define COMSIG_ACTION_TRIGGER "action_trigger"
+ #define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0)
+
+//Xenobio hotkeys
+
+///from slime CtrlClickOn(): (/mob)
+#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl"
+///from slime AltClickOn(): (/mob)
+#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt"
+///from slime ShiftClickOn(): (/mob)
+#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift"
+///from turf ShiftClickOn(): (/mob)
+#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift"
+///from turf AltClickOn(): (/mob)
+#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt"
+///from monkey CtrlClickOn(): (/mob)
+#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl"
diff --git a/code/__DEFINES/gamemode.dm b/code/__DEFINES/gamemode.dm
index 73a812e8f5b..2de0a86c268 100644
--- a/code/__DEFINES/gamemode.dm
+++ b/code/__DEFINES/gamemode.dm
@@ -15,6 +15,7 @@
#define GAMEMODE_IS_NUCLEAR (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear))
#define GAMEMODE_IS_REVOLUTION (SSticker && istype(SSticker.mode, /datum/game_mode/revolution))
#define GAMEMODE_IS_WIZARD (SSticker && istype(SSticker.mode, /datum/game_mode/wizard))
+#define GAMEMODE_IS_RAGIN_MAGES (SSticker && istype(SSticker.mode, /datum/game_mode/wizard/raginmages))
//special roles
// Distinct from the ROLE_X defines because some antags have multiple special roles but only one ban type
diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index b446a5407ac..5fd85513501 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -24,78 +24,61 @@
///////////////////////////////////////
// MUTATIONS
///////////////////////////////////////
+
// Generic mutations:
-#define TK 1
-#define COLDRES 2
-#define XRAY 3
-#define HULK 4
-#define CLUMSY 5
-#define FAT 6
-#define HUSK 7
-#define NOCLONE 8
-
-// Extra powers:
-#define LASER 9 // harm intent - click anywhere to shoot lasers from eyes
-
-//species mutation
-#define WINGDINGS 10 // Ayy lmao
-
-//2spooky
-#define SKELETON 29
-#define PLANT 30
-
-// Other Mutations:
-#define BREATHLESS 100 // no breathing
-#define REMOTE_VIEW 101 // remote viewing
-#define REGEN 102 // health regen
-#define RUN 103 // no slowdown
-#define REMOTE_TALK 104 // remote talking
-#define MORPH 105 // changing appearance
-#define HEATRES 106 // heat resistance
-#define HALLUCINATE 107 // hallucinations
-#define FINGERPRINTS 108 // no fingerprints
-#define NO_SHOCK 109 // insulated hands
-#define DWARF 110 // table climbing
-
-// Goon muts
-#define OBESITY 200 // Decreased metabolism
-// 201 undefined
-#define STRONG 202 // (Nothing)
-#define SOBER 203 // Increased alcohol metabolism
-#define PSY_RESIST 204 // Block remoteview
-// 205 undefined
-#define EMPATH 206 //Read minds
-#define COMIC 207 //Comic Sans
-
-// /vg/ muts
-#define LOUD 208 // CAUSES INTENSE YELLING
-#define DIZZY 210 // Trippy.
-
-#define LISP 300
-#define RADIOACTIVE 301
-#define CHAV 302
-#define SWEDISH 303
-#define SCRAMBLED 304
-#define HORNS 305
-#define IMMOLATE 306
-#define CLOAK 307
-#define CHAMELEON 308
-#define CRYO 309
-#define EATER 310
-
-#define JUMPY 400
-#define POLYMORPH 401
-
+#define TK "telekenesis"
+#define COLDRES "cold_resistance"
+#define XRAY "xray"
+#define HULK "hulk"
+#define CLUMSY "clumsy"
+#define FAT "fat"
+#define HUSK "husk"
+#define NOCLONE "noclone"
+#define LASER "eyelaser" // harm intent - click anywhere to shoot lasers from eyes
+#define WINGDINGS "wingdings" // Ayy lmao
+#define SKELETON "skeleton"
+#define BREATHLESS "breathless" // no breathing
+#define REMOTE_VIEW "remove_view" // remote viewing
+#define REGEN "regeneration" // health regen
+#define RUN "increased_run" // no slowdown
+#define REMOTE_TALK "remote_talk" // remote talking
+#define MORPH "morph" // changing appearance
+#define HEATRES "heat_resistance" // heat resistance
+#define HALLUCINATE "hallucinate" // hallucinations
+#define FINGERPRINTS "no_prints" // no fingerprints
+#define NO_SHOCK "no_shock" // insulated hands
+#define DWARF "dwarf" // table climbing
+#define OBESITY "obesity" // Decreased metabolism
+#define STRONG "strong" // (Nothing)
+#define SOBER "sober" // Increased alcohol metabolism
+#define PSY_RESIST "psy_resist" // Block remoteview
+#define EMPATH "empathy" //Read minds
+#define COMIC "comic_sans" //Comic Sans
+#define LOUD "loudness" // CAUSES INTENSE YELLING
+#define DIZZY "dizzy" // Trippy.
+#define LISP "lisp"
+#define RADIOACTIVE "radioactive"
+#define CHAV "chav"
+#define SWEDISH "swedish"
+#define SCRAMBLED "scrambled"
+#define HORNS "horns"
+#define IMMOLATE "immolate"
+#define CLOAK "cloak"
+#define CHAMELEON "chameleon"
+#define CRYO "cryokinesis"
+#define EATER "matter_eater"
+#define JUMPY "jumpy"
+#define POLYMORPH "polymorph"
//disabilities
-#define NEARSIGHTED 1
-#define EPILEPSY 2
-#define COUGHING 4
-#define TOURETTES 8
-#define NERVOUS 16
-#define BLIND 32
-#define COLOURBLIND 64
-#define MUTE 128
-#define DEAF 256
+#define NEARSIGHTED "nearsighted"
+#define EPILEPSY "epilepsy"
+#define COUGHING "coughing"
+#define TOURETTES "tourettes"
+#define NERVOUS "nervous"
+#define BLINDNESS "blind"
+#define COLOURBLIND "colorblind"
+#define MUTE "mute"
+#define DEAF "deaf"
//Nutrition levels for humans. No idea where else to put it
#define NUTRITION_LEVEL_FAT 600
@@ -152,7 +135,6 @@
#define NO_SCAN "no_scan"
#define NO_PAIN "no_pain"
#define IS_PLANT "is_plant"
-#define CAN_BE_FAT "can_be_fat"
#define NO_INTORGANS "no_internal_organs"
#define RADIMMUNE "rad_immunity"
#define NOGUNS "no_guns"
@@ -163,7 +145,6 @@
#define RESISTCOLD "resist_cold"
#define NO_EXAMINE "no_examine"
#define CAN_WINGDINGS "can_wingdings"
-#define NOZOMBIE "no_zombie"
#define NO_GERMS "no_germs"
#define NO_DECAY "no_decay"
#define PIERCEIMMUNE "pierce_immunity"
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index cec707b8196..23ac017f1ec 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -5,6 +5,3 @@
#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in an inventory, ex: Defibrillator, Backpack, Space Suits
#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons
#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe
-
-#define TV_TRIP "trip"
-#define TV_SLIP "slip"
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 671897b612d..2b8c515e81a 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -1,10 +1,8 @@
// Atoms
-#define isatom(A) istype(A, /atom)
-#define ismovableatom(A) istype(A, /atom/movable)
+#define isatom(A) (isloc(A))
// Mobs
#define ismegafauna(A) istype(A, /mob/living/simple_animal/hostile/megafauna)
-#define iszombie(A) (is_species(A, /datum/species/zombie))
//Simple animals
#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm
index d72628e2cb7..349d1b246be 100644
--- a/code/__DEFINES/job.dm
+++ b/code/__DEFINES/job.dm
@@ -51,7 +51,7 @@
#define JOB_CLOWN (1<<11)
#define JOB_MIME (1<<12)
#define JOB_CIVILIAN (1<<13)
-
+#define JOB_EXPLORER (1<<14)
#define JOBCAT_KARMA (1<<3)
diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm
index 01dbc2f1c2b..34528090e86 100644
--- a/code/__DEFINES/lighting.dm
+++ b/code/__DEFINES/lighting.dm
@@ -90,3 +90,27 @@
#define FLASH_LIGHT_DURATION 2
#define FLASH_LIGHT_POWER 3
#define FLASH_LIGHT_RANGE 3.8
+
+/// Returns the red part of a #RRGGBB hex sequence as number
+#define GETREDPART(hexa) hex2num(copytext(hexa, 2, 4))
+
+/// Returns the green part of a #RRGGBB hex sequence as number
+#define GETGREENPART(hexa) hex2num(copytext(hexa, 4, 6))
+
+/// Returns the blue part of a #RRGGBB hex sequence as number
+#define GETBLUEPART(hexa) hex2num(copytext(hexa, 6, 8))
+
+/// Parse the hexadecimal color into lumcounts of each perspective.
+#define PARSE_LIGHT_COLOR(source) \
+do { \
+ if (source.light_color) { \
+ var/__light_color = source.light_color; \
+ source.lum_r = GETREDPART(__light_color) / 255; \
+ source.lum_g = GETGREENPART(__light_color) / 255; \
+ source.lum_b = GETBLUEPART(__light_color) / 255; \
+ } else { \
+ source.lum_r = 1; \
+ source.lum_g = 1; \
+ source.lum_b = 1; \
+ }; \
+} while (FALSE)
diff --git a/code/__DEFINES/math.dm b/code/__DEFINES/math.dm
index 2f2968561da..433d1c55b56 100644
--- a/code/__DEFINES/math.dm
+++ b/code/__DEFINES/math.dm
@@ -1,59 +1,238 @@
+#define NUM_E 2.71828183
+
#define PI 3.1415
-#define SPEED_OF_LIGHT 3e8 //not exact but hey!
-#define SPEED_OF_LIGHT_SQ 9e+16
#define INFINITY 1e31 //closer than enough
-#define Clamp(x, y, z) ((x) <= (y) ? (y) : ((x) >= (z) ? (z) : (x)))
-#define CLAMP01(x) (Clamp((x), 0, 1))
-
-// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
-#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
-
-#define SIMPLE_SIGN(X) ((X) < 0 ? -1 : 1)
-#define SIGN(X) ((X) ? SIMPLE_SIGN(X) : 0)
-#define hypotenuse(Ax, Ay, Bx, By) (sqrt(((Ax) - (Bx))**2 + ((Ay) - (By))**2))
-#define Ceiling(x) (-round(-(x)))
-#define Tan(x) (sin(x) / cos(x))
-#define Cot(x) (1 / Tan(x))
-#define Csc(x) (1 / sin(x))
-#define Sec(x) (1 / cos(x))
-#define Floor(x) (round(x))
-#define Inverse(x) (1 / (x))
-#define IsEven(x) ((x) % 2 == 0)
-#define IsOdd(x) ((x) % 2 == 1)
-#define IsInRange(val, min, max) ((min) <= (val) && (val) <= (max))
-#define IsInteger(x) (Floor(x) == (x))
-#define IsMultiple(x, y) ((x) % (y) == 0)
-#define Lcm(a, b) (abs(a) / Gcd((a), (b)) * abs(b))
-#define Root(n, x) ((x) ** (1 / (n)))
-#define ToDegrees(radians) ((radians) * 57.2957795) // 180 / Pi
-#define ToRadians(degrees) ((degrees) * 0.0174532925) // Pi / 180
-
#define SHORT_REAL_LIMIT 16777216
-// Real modulus that handles decimals
-#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
-
-
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
//collapsed to percent_of_tick_used * tick_lag
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
+#define PERCENT(val) (round((val)*100, 0.1))
+#define CLAMP01(x) (clamp(x, 0, 1))
+
//time of day but automatically adjusts to the server going into the next day within the same round.
//for when you need a reliable time number that doesn't depend on byond time.
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
#define MIDNIGHT_ROLLOVER_CHECK ( GLOB.rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : GLOB.midnight_rollovers )
+#define SIMPLE_SIGN(X) ((X) < 0 ? -1 : 1)
+
+#define SIGN(x) ( (x)!=0 ? (x) / abs(x) : 0 )
+
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
+// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
+#define WRAP(val, min, max) clamp(( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) ),min,max)
+
+// Real modulus that handles decimals
+#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
+
+// Cotangent
+#define COT(x) (1 / tan(x))
+
+// Secant
+#define SEC(x) (1 / cos(x))
+
+// Cosecant
+#define CSC(x) (1 / sin(x))
+
+#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
+
+#define HYPOTENUSE(Ax, Ay, Bx, By) (sqrt(((Ax) - (Bx))**2 + ((Ay) - (By))**2))
+
+// Greatest Common Divisor - Euclid's algorithm
+/proc/Gcd(a, b)
+ return b ? Gcd(b, (a) % (b)) : a
+
+// Least Common Multiple
+#define Lcm(a, b) (abs(a) / Gcd(a, b) * abs(b))
+
+#define INVERSE(x) ( 1/(x) )
+
+// Used for calculating the radioactive strength falloff
+#define INVERSE_SQUARE(initial_strength,cur_distance,initial_distance) ( (initial_strength)*((initial_distance)**2/(cur_distance)**2) )
+
+#define ISABOUTEQUAL(a, b, deviation) (deviation ? abs((a) - (b)) <= deviation : abs((a) - (b)) <= 0.1)
+
+#define ISEVEN(x) (x % 2 == 0)
+
+#define ISODD(x) (x % 2 != 0)
+
+// Returns true if val is from min to max, inclusive.
+#define ISINRANGE(val, min, max) (min <= val && val <= max)
+
+// Same as above, exclusive.
+#define ISINRANGE_EX(val, min, max) (min < val && val < max)
+
+#define ISINTEGER(x) (round(x) == x)
+
+#define ISMULTIPLE(x, y) ((x) % (y) == 0)
+
+// Performs a linear interpolation between a and b.
+// Note that amount=0 returns a, amount=1 returns b, and
+// amount=0.5 returns the mean of a and b.
+#define LERP(a, b, amount) ( amount ? ((a) + ((b) - (a)) * (amount)) : a )
+
+// Returns the nth root of x.
+#define ROOT(n, x) ((x) ** (1 / (n)))
+
+// The quadratic formula. Returns a list with the solutions, or an empty list
+// if they are imaginary.
+/proc/SolveQuadratic(a, b, c)
+ ASSERT(a)
+ . = list()
+ var/d = b*b - 4 * a * c
+ var/bottom = 2 * a
+ if(d < 0)
+ return
+ var/root = sqrt(d)
+ . += (-b + root) / bottom
+ if(!d)
+ return
+ . += (-b - root) / bottom
+
+#define TODEGREES(radians) ((radians) * 57.2957795)
+
+#define TORADIANS(degrees) ((degrees) * 0.0174532925)
+
+/// Gets shift x that would be required the bitflag (1< dec? -dec : inc
+
+//A logarithm that converts an integer to a number scaled between 0 and 1.
+//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
+#define TRANSFORM_USING_VARIABLE(input, max) ( sin((90*(input))/(max))**2 )
+
+//converts a uniform distributed random number into a normal distributed one
+//since this method produces two random numbers, one is saved for subsequent calls
+//(making the cost negligble for every second call)
+//This will return +/- decimals, situated about mean with standard deviation stddev
+//68% chance that the number is within 1stddev
+//95% chance that the number is within 2stddev
+//98% chance that the number is within 3stddev...etc
+#define ACCURACY 10000
+/proc/gaussian(mean, stddev)
+ var/static/gaussian_next
+ var/R1;var/R2;var/working
+ if(gaussian_next != null)
+ R1 = gaussian_next
+ gaussian_next = null
+ else
+ do
+ R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
+ R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
+ working = R1*R1 + R2*R2
+ while(working >= 1 || working==0)
+ working = sqrt(-2 * log(working) / working)
+ R1 *= working
+ gaussian_next = R2 * working
+ return (mean + stddev * R1)
+#undef ACCURACY
+
+/proc/get_turf_in_angle(angle, turf/starting, increments)
+ var/pixel_x = 0
+ var/pixel_y = 0
+ for(var/i in 1 to increments)
+ pixel_x += sin(angle)+16*sin(angle)*2
+ pixel_y += cos(angle)+16*cos(angle)*2
+ var/new_x = starting.x
+ var/new_y = starting.y
+ while(pixel_x > 16)
+ pixel_x -= 32
+ new_x++
+ while(pixel_x < -16)
+ pixel_x += 32
+ new_x--
+ while(pixel_y > 16)
+ pixel_y -= 32
+ new_y++
+ while(pixel_y < -16)
+ pixel_y += 32
+ new_y--
+ new_x = clamp(new_x, 0, world.maxx)
+ new_y = clamp(new_y, 0, world.maxy)
+ return locate(new_x, new_y, starting.z)
+
+// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
+/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
+ var/list/region_x1 = list()
+ var/list/region_y1 = list()
+ var/list/region_x2 = list()
+ var/list/region_y2 = list()
+
+ // These loops create loops filled with x/y values that the boundaries inhabit
+ // ex: list(5, 6, 7, 8, 9)
+ for(var/i in min(x1, x2) to max(x1, x2))
+ region_x1["[i]"] = TRUE
+ for(var/i in min(y1, y2) to max(y1, y2))
+ region_y1["[i]"] = TRUE
+ for(var/i in min(x3, x4) to max(x3, x4))
+ region_x2["[i]"] = TRUE
+ for(var/i in min(y3, y4) to max(y3, y4))
+ region_y2["[i]"] = TRUE
+
+ return list(region_x1 & region_x2, region_y1 & region_y2)
+
+#define EXP_DISTRIBUTION(desired_mean) ( -(1/(1/desired_mean)) * log(rand(1, 1000) * 0.001) )
+
+#define LORENTZ_DISTRIBUTION(x, s) ( s*tan(TODEGREES(PI*(rand()-0.5))) + x )
+#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )
+
+#define RULE_OF_THREE(a, b, x) ((a*x)/b)
+// )
+
+/proc/RaiseToPower(num, power)
+ if(!power)
+ return 1
+ return (power-- > 1 ? num * RaiseToPower(num, power) : num)
+
+// oof, what a mouthful
+// Used in status_procs' "adjust" to let them modify a status effect by a given
+// amount, without inadverdently increasing it in the wrong direction
+/proc/directional_bounded_sum(orig_val, modifier, bound_lower, bound_upper)
+ var/new_val = orig_val + modifier
+ if(modifier > 0)
+ if(new_val > bound_upper)
+ new_val = max(orig_val, bound_upper)
+ else if(modifier < 0)
+ if(new_val < bound_lower)
+ new_val = min(orig_val, bound_lower)
+ return new_val
+
+// sqrt, but if you give it a negative number, you get 0 instead of a runtime
+/proc/sqrtor0(num)
+ if(num < 0)
+ return 0
+ return sqrt(num)
+
+/proc/round_down(num)
+ if(round(num) != num)
+ return round(num--)
+ else
+ return num
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 7eaaa86747e..ad5e5df7583 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -319,7 +319,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
-#define SQL_VERSION 11
+#define SQL_VERSION 12
// Vending machine stuff
#define CAT_NORMAL 1
@@ -345,7 +345,7 @@
#define MOUSE_OPACITY_OPAQUE 2
// Defib stats
-#define DEFIB_TIME_LIMIT 120
+#define DEFIB_TIME_LIMIT 300
#define DEFIB_TIME_LOSS 60
//different types of atom colorations
@@ -431,7 +431,6 @@
#define LINDA_SPAWN_OXYGEN 8
#define LINDA_SPAWN_CO2 16
#define LINDA_SPAWN_NITROGEN 32
-
#define LINDA_SPAWN_N2O 64
-
+#define LINDA_SPAWN_AGENT_B 128
#define LINDA_SPAWN_AIR 256
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index e1e15a926d6..719274857ec 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -196,7 +196,7 @@
#define isslimeperson(A) (is_species(A, /datum/species/slime))
#define isgrey(A) (is_species(A, /datum/species/grey))
#define isdiona(A) (is_species(A, /datum/species/diona))
-#define ismachine(A) (is_species(A, /datum/species/machine))
+#define ismachineperson(A) (is_species(A, /datum/species/machine))
#define isdrask(A) (is_species(A, /datum/species/drask))
#define isanimal(A) (istype((A), /mob/living/simple_animal))
diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm
index e0c71836c72..ec65a37642f 100644
--- a/code/__DEFINES/radio.dm
+++ b/code/__DEFINES/radio.dm
@@ -58,3 +58,10 @@
#define RADIO_MEDBOT "12"
#define RADIO_MAGNETS "radio_magnet"
#define RADIO_LOGIC "radio_logic"
+
+// Signal types
+#define SIGNALTYPE_NORMAL 0
+#define SIGNALTYPE_INTERCOM 1 // Will only broadcast to intercoms
+#define SIGNALTYPE_INTERCOM_SBR 2 // Will only broadcast to intercoms and station-bounced radios
+#define SIGNALTYPE_AINOTRACK 4 // AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob
+
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 2b9e2c56b4d..8021fa4452d 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -48,7 +48,7 @@
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
//(in game days played) to play that role
-var/global/list/special_roles = list(
+GLOBAL_LIST_INIT(special_roles, list(
ROLE_ABDUCTOR = /datum/game_mode/abduction, // Abductor
ROLE_BLOB = /datum/game_mode/blob, // Blob
ROLE_CHANGELING = /datum/game_mode/changeling, // Changeling
@@ -72,10 +72,10 @@ var/global/list/special_roles = list(
ROLE_VAMPIRE = /datum/game_mode/vampire, // Vampire
ROLE_RAIDER = /datum/game_mode/heist, // Vox raider
ROLE_ALIEN, // Xenomorph
- ROLE_WIZARD = /datum/game_mode/wizard, // Wizard
+ ROLE_WIZARD = /datum/game_mode/wizard // Wizard
// UNUSED/BROKEN ANTAGS
// ROLE_HOG_GOD = /datum/game_mode/hand_of_god,
// ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god,
// ROLE_MONKEY = /datum/game_mode/monkey, Sooner or later these are going to get ported
-// ROLE_GANG = /datum/game_mode/gang,
-)
+// ROLE_GANG = /datum/game_mode/gang
+))
diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm
index b0274e9d802..c15dfd78b0f 100644
--- a/code/__DEFINES/sound.dm
+++ b/code/__DEFINES/sound.dm
@@ -15,3 +15,57 @@
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 0.5
+
+//Ambience types
+
+#define GENERIC_SOUNDS list('sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg',\
+ 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg',\
+ 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen7.ogg',\
+ 'sound/ambience/ambigen8.ogg', 'sound/ambience/ambigen9.ogg',\
+ 'sound/ambience/ambigen10.ogg', 'sound/ambience/ambigen11.ogg',\
+ 'sound/ambience/ambigen12.ogg', 'sound/ambience/ambigen14.ogg', 'sound/ambience/ambigen15.ogg')
+
+#define HOLY_SOUNDS list('sound/ambience/ambicha1.ogg', 'sound/ambience/ambicha2.ogg', 'sound/ambience/ambicha3.ogg',\
+ 'sound/ambience/ambicha4.ogg', 'sound/ambience/ambiholy.ogg', 'sound/ambience/ambiholy2.ogg',\
+ 'sound/ambience/ambiholy3.ogg')
+
+#define HIGHSEC_SOUNDS list('sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg')
+
+#define RUINS_SOUNDS list('sound/ambience/ambimine.ogg', 'sound/ambience/ambicave.ogg', 'sound/ambience/ambiruin.ogg',\
+ 'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
+ 'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
+ 'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambitech3.ogg',\
+ 'sound/ambience/ambimystery.ogg', 'sound/ambience/ambimaint1.ogg')
+
+#define ENGINEERING_SOUNDS list('sound/ambience/ambisin1.ogg', 'sound/ambience/ambisin2.ogg', 'sound/ambience/ambisin3.ogg', 'sound/ambience/ambisin4.ogg',\
+ 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambitech3.ogg')
+
+#define MINING_SOUNDS list('sound/ambience/ambimine.ogg', 'sound/ambience/ambicave.ogg', 'sound/ambience/ambiruin.ogg',\
+ 'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
+ 'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
+ 'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint1.ogg',\
+ 'sound/ambience/ambilava1.ogg', 'sound/ambience/ambilava2.ogg', 'sound/ambience/ambilava3.ogg')
+
+#define MEDICAL_SOUNDS list('sound/ambience/ambinice.ogg')
+
+#define SPOOKY_SOUNDS list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/ambience/ambiruin7.ogg','sound/ambience/ambiruin6.ogg',\
+ 'sound/ambience/ambiodd.ogg', 'sound/ambience/ambimystery.ogg')
+
+#define SPACE_SOUNDS list('sound/ambience/ambispace.ogg', 'sound/ambience/ambispace2.ogg', 'sound/music/title2.ogg', 'sound/ambience/ambiatmos.ogg')
+
+#define MAINTENANCE_SOUNDS list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg',\
+ 'sound/ambience/ambimaint5.ogg', 'sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg', 'sound/ambience/ambitech2.ogg' )
+
+#define AWAY_MISSION_SOUNDS list('sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiruin.ogg',\
+ 'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\
+ 'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
+ 'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint.ogg',\
+ 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg', 'sound/ambience/ambiodd.ogg')
+
+
+
+#define CREEPY_SOUNDS list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\
+ 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
+ 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
+ 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
+ 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm
index b0a74b6c702..c9763e4836c 100644
--- a/code/__DEFINES/stat.dm
+++ b/code/__DEFINES/stat.dm
@@ -3,7 +3,7 @@
#define UNCONSCIOUS 1
#define DEAD 2
-// NanoUI flags
+// NanoUI & TGUI flags
#define STATUS_INTERACTIVE 2 // GREEN Visability
#define STATUS_UPDATE 1 // ORANGE Visability
#define STATUS_DISABLED 0 // RED Visability
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 300d3a41fc0..153eca7f373 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -44,7 +44,7 @@
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
-
+#define INIT_ORDER_TITLE 100 // This **MUST** load first or people will se blank lobby screens
#define INIT_ORDER_GARBAGE 19
#define INIT_ORDER_DBCORE 18
#define INIT_ORDER_BLACKBOX 17
@@ -66,6 +66,7 @@
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_AIR -1
+#define INIT_ORDER_SUN -2
#define INIT_ORDER_MINIMAP -3
#define INIT_ORDER_ASSETS -4
#define INIT_ORDER_ICON_SMOOTHING -5
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index f5d582f5e42..a3154834fe4 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -143,6 +143,9 @@ GLOBAL_VAR_INIT(log_end, (world.system_type == UNIX ? ascii2text(13) : ""))
/proc/log_runtime_summary(text)
WRITE_LOG(GLOB.runtime_summary_log, "[text]")
+/proc/log_tgui(text)
+ WRITE_LOG(GLOB.tgui_log, "[text]")
+
/**
* Standardized method for tracking startup times.
*/
diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm
index f8817c2e8e6..0a58ed035f7 100644
--- a/code/__HELPERS/files.dm
+++ b/code/__HELPERS/files.dm
@@ -18,6 +18,8 @@
src << browse_rsc(file)
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm"))
+ // wow why was this ever a parameter
+ root = "data/logs/"
var/path = root
for(var/i=0, ipAI software module [P.name] has the same key as [O.name]!")
+ continue
+ GLOB.pai_software_by_key[P.id] = P
+ if(P.default)
+ GLOB.default_pai_software[P.id] = P
+
+ // Setup loadout gear
+ for(var/geartype in subtypesof(/datum/gear))
+ var/datum/gear/G = geartype
+
+ var/use_name = initial(G.display_name)
+ var/use_category = initial(G.sort_category)
+
+ if(G == initial(G.subtype_path))
+ continue
+
+ if(!use_name)
+ error("Loadout - Missing display name: [G]")
+ continue
+ if(!initial(G.cost))
+ error("Loadout - Missing cost: [G]")
+ continue
+ if(!initial(G.path))
+ error("Loadout - Missing path definition: [G]")
+ continue
+
+ if(!GLOB.loadout_categories[use_category])
+ GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category)
+ var/datum/loadout_category/LC = GLOB.loadout_categories[use_category]
+ GLOB.gear_datums[use_name] = new geartype
+ LC.gear[use_name] = GLOB.gear_datums[use_name]
+
+ GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories)
+ for(var/loadout_category in GLOB.loadout_categories)
+ var/datum/loadout_category/LC = GLOB.loadout_categories[loadout_category]
+ LC.gear = sortAssoc(LC.gear)
+
+
+ // Setup a list of robolimbs
+ GLOB.basic_robolimb = new()
+ for(var/limb_type in typesof(/datum/robolimb))
+ var/datum/robolimb/R = new limb_type()
+ GLOB.all_robolimbs[R.company] = R
+ if(!R.unavailable_at_chargen)
+ if(R != "head" && R != "chest" && R != "groin" ) //Part of the method that ensures only IPCs can access head, chest and groin prosthetics.
+ if(R.has_subtypes) //Ensures solos get added to the list as well be incorporating has_subtypes == 1 and has_subtypes == 2.
+ GLOB.chargen_robolimbs[R.company] = R //List only main brands and solo parts.
+ if(R.selectable)
+ GLOB.selectable_robolimbs[R.company] = R
/* // Uncomment to debug chemical reaction list.
/client/verb/debug_chemical_list()
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index dc256a93478..caa8291b4bb 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -61,7 +61,7 @@
var/adjacencies = 0
var/atom/movable/AM
- if(ismovableatom(A))
+ if(ismovable(A))
AM = A
if(AM.can_be_unanchored && !AM.anchored)
return 0
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index fe904e6c2ed..ef0f47b2f9c 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -570,6 +570,18 @@ world
/proc/BlendRGBasHSV(rgb1, rgb2, amount)
return HSVtoRGB(RGBtoHSV(rgb1), RGBtoHSV(rgb2), amount)
+//Returns the perceived brightness of a color.
+//https://en.wikipedia.org/wiki/Relative_luminance
+//https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
+/proc/getLuminance(color)
+ var/list/RGB = ReadRGB(color)
+ var/R = RGB[1]
+ var/G = RGB[2]
+ var/B = RGB[2]
+
+ var/Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B)
+ return clamp((Y * 0.01), 0, 1) //Returns the brightness of a color in decimal percentage format. Can multiply light_power by this to receive 100% brightness or a lower brightness. Not a higher brightness.
+
/proc/HueToAngle(hue)
// normalize hsv in case anything is screwy
if(hue < 0 || hue >= 1536) hue %= 1536
@@ -887,9 +899,9 @@ The _flatIcons list is a cache for generated icon files.
if(!value) return color
var/list/RGB = ReadRGB(color)
- RGB[1] = Clamp(RGB[1]+value,0,255)
- RGB[2] = Clamp(RGB[2]+value,0,255)
- RGB[3] = Clamp(RGB[3]+value,0,255)
+ RGB[1] = clamp(RGB[1]+value,0,255)
+ RGB[2] = clamp(RGB[2]+value,0,255)
+ RGB[3] = clamp(RGB[3]+value,0,255)
return rgb(RGB[1],RGB[2],RGB[3])
/proc/sort_atoms_by_layer(var/list/atoms)
diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 7d1b8ee6ebc..f9b9850bd2d 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -690,6 +690,8 @@ proc/dd_sortedObjectList(list/incoming)
// LAZYING PT 2: THE LAZENING
#define LAZYREINITLIST(L) LAZYCLEARLIST(L); LAZYINITLIST(L);
+// Lazying Episode 3
+#define LAZYSET(L, K, V) LAZYINITLIST(L); L[K] = V;
//same, but returns nothing and acts on list in place
/proc/shuffle_inplace(list/L)
diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm
deleted file mode 100644
index 76d422e3d82..00000000000
--- a/code/__HELPERS/maths.dm
+++ /dev/null
@@ -1,143 +0,0 @@
-// Credits to Nickr5 for the useful procs I've taken from his library resource.
-
-#define MATH_E 2.71828183
-#define SQRT2 1.41421356
-
-/proc/Atan2(x, y)
- if(!x && !y) return 0
- var/a = arccos(x / sqrt(x*x + y*y))
- return y >= 0 ? a : -a
-
-// Greatest Common Divisor - Euclid's algorithm
-/proc/Gcd(a, b)
- return b ? Gcd(b, a % b) : a
-
-/proc/IsAboutEqual(a, b, deviation = 0.1)
- return abs(a - b) <= deviation
-
-// Performs a linear interpolation between a and b.
-// Note that amount=0 returns a, amount=1 returns b, and
-// amount=0.5 returns the mean of a and b.
-/proc/Lerp(a, b, amount = 0.5)
- return a + (b - a) * amount
-
-/proc/Mean(...)
- var/values = 0
- var/sum = 0
- for(var/val in args)
- values++
- sum += val
- return sum / values
-
-// The quadratic formula. Returns a list with the solutions, or an empty list
-// if they are imaginary.
-/proc/SolveQuadratic(a, b, c)
- ASSERT(a)
- . = list()
- var/d = b*b - 4 * a * c
- var/bottom = 2 * a
- if(d < 0) return
- var/root = sqrt(d)
- . += (-b + root) / bottom
- if(!d) return
- . += (-b - root) / bottom
-
-// Will filter out extra rotations and negative rotations
-// E.g: 540 becomes 180. -180 becomes 180.
-/proc/SimplifyDegrees(degrees)
- degrees = degrees % 360
- if(degrees < 0)
- degrees += 360
- return degrees
-
-// min is inclusive, max is exclusive
-/proc/Wrap(val, min, max)
- var/d = max - min
- var/t = Floor((val - min) / d)
- return val - (t * d)
-
-//A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher).
-//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
-/proc/TransformUsingVariable(input, inputmaximum, scaling_modifier = 0)
-
- var/inputToDegrees = (input/inputmaximum)*180 //Converting from a 0 -> 100 scale to a 0 -> 180 scale. The 0 -> 180 scale corresponds to degrees
- var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1
-
- return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
- //world<< "Transform multiplier of [src] is [size_factor + scaling_modifer]"
-
-/proc/RaiseToPower(num, power)
- if(!power) return 1
- return (power-- > 1 ? num * RaiseToPower(num, power) : num)
-
-//converts a uniform distributed random number into a normal distributed one
-//since this method produces two random numbers, one is saved for subsequent calls
-//(making the cost negligble for every second call)
-//This will return +/- decimals, situated about mean with standard deviation stddev
-//68% chance that the number is within 1stddev
-//95% chance that the number is within 2stddev
-//98% chance that the number is within 3stddev...etc
-GLOBAL_VAR(gaussian_next)
-#define ACCURACY 10000
-/proc/gaussian(mean, stddev)
- var/R1;var/R2;var/working
- if(GLOB.gaussian_next != null)
- R1 = GLOB.gaussian_next
- GLOB.gaussian_next = null
- else
- do
- R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
- R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
- working = R1*R1 + R2*R2
- while(working >= 1 || working==0)
- working = sqrt(-2 * log(working) / working)
- R1 *= working
- GLOB.gaussian_next = R2 * working
- return (mean + stddev * R1)
-#undef ACCURACY
-
-
-
-// oof, what a mouthful
-// Used in status_procs' "adjust" to let them modify a status effect by a given
-// amount, without inadverdently increasing it in the wrong direction
-/proc/directional_bounded_sum(orig_val, modifier, bound_lower, bound_upper)
- var/new_val = orig_val + modifier
- if(modifier > 0)
- if(new_val > bound_upper)
- new_val = max(orig_val, bound_upper)
- else if(modifier < 0)
- if(new_val < bound_lower)
- new_val = min(orig_val, bound_lower)
- return new_val
-
-// sqrt, but if you give it a negative number, you get 0 instead of a runtime
-/proc/sqrtor0(num)
- if(num < 0)
- return 0
- return sqrt(num)
-
-/proc/round_down(num)
- if(round(num) != num)
- return round(num--)
- else return num
-
-// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
-/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
- var/list/region_x1 = list()
- var/list/region_y1 = list()
- var/list/region_x2 = list()
- var/list/region_y2 = list()
-
- // These loops create loops filled with x/y values that the boundaries inhabit
- // ex: list(5, 6, 7, 8, 9)
- for(var/i in min(x1, x2) to max(x1, x2))
- region_x1["[i]"] = TRUE
- for(var/i in min(y1, y2) to max(y1, y2))
- region_y1["[i]"] = TRUE
- for(var/i in min(x3, x4) to max(x3, x4))
- region_x2["[i]"] = TRUE
- for(var/i in min(y3, y4) to max(y3, y4))
- region_y2["[i]"] = TRUE
-
- return list(region_x1 & region_x2, region_y1 & region_y2)
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index ff127fd3a48..0d3b26d0340 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -244,21 +244,27 @@ proc/age2agedescription(age)
var/their_rank = target_records.fields["rank"]
switch(criminal_status)
if("arrest")
- status = "*Arrest*"
+ status = SEC_RECORD_STATUS_ARREST
if("none")
- status = "None"
+ status = SEC_RECORD_STATUS_NONE
if("execute")
if((ACCESS_MAGISTRATE in authcard_access) || (ACCESS_ARMORY in authcard_access))
- status = "*Execute*"
+ status = SEC_RECORD_STATUS_EXECUTE
message_admins("[ADMIN_FULLMONTY(usr)] authorized EXECUTION for [their_rank] [their_name], with comment: [comment]")
else
return 0
+ if("search")
+ status = SEC_RECORD_STATUS_SEARCH
+ if("monitor")
+ status = SEC_RECORD_STATUS_MONITOR
+ if ("demote")
+ status = SEC_RECORD_STATUS_DEMOTE
if("incarcerated")
- status = "Incarcerated"
+ status = SEC_RECORD_STATUS_INCARCERATED
if("parolled")
- status = "Parolled"
+ status = SEC_RECORD_STATUS_PAROLLED
if("released")
- status = "Released"
+ status = SEC_RECORD_STATUS_RELEASED
target_records.fields["criminal"] = status
log_admin("[key_name_admin(user)] set secstatus of [their_rank] [their_name] to [status], comment: [comment]")
target_records.fields["comments"] += "Set to [status] by [user.name] ([user_rank]) on [GLOB.current_date_string] [station_time_timestamp()], comment: [comment]"
@@ -277,17 +283,20 @@ This is always put in the attack log.
/proc/add_attack_logs(atom/user, target, what_done, custom_level)
if(islist(target)) // Multi-victim adding
var/list/targets = target
- for(var/mob/M in targets)
- add_attack_logs(user, M, what_done, custom_level)
+ for(var/t in targets)
+ add_attack_logs(user, t, what_done, custom_level)
return
var/user_str = key_name_log(user) + COORD(user)
var/target_str
+ var/target_info
if(isatom(target))
var/atom/AT = target
target_str = key_name_log(AT) + COORD(AT)
+ target_info = key_name_admin(target)
else
target_str = target
+ target_info = target
var/mob/MU = user
var/mob/MT = target
if(istype(MU))
@@ -311,12 +320,15 @@ This is always put in the attack log.
var/area/A = get_area(MT)
if(A && A.hide_attacklogs)
loglevel = ATKLOG_ALMOSTALL
+ else
+ loglevel = ATKLOG_ALL // Hitting an object. Not a mob
if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level
loglevel = ATKLOG_FEW
- msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]", loglevel)
-/proc/do_mob(var/mob/user, var/mob/target, var/time = 30, var/uninterruptible = 0, progress = 1, datum/callback/extra_checks = null)
+ msg_admin_attack("[key_name_admin(user)] vs [target_info]: [what_done]", loglevel)
+
+/proc/do_mob(mob/user, mob/target, time = 30, uninterruptible = 0, progress = 1, list/extra_checks = list())
if(!user || !target)
return 0
var/user_loc = user.loc
@@ -349,7 +361,7 @@ This is always put in the attack log.
drifting = 0
user_loc = user.loc
- if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
+ if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying || check_for_true_callbacks(extra_checks))
. = 0
break
if(progress)
@@ -454,8 +466,8 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
/proc/do_after_once_checks(cache_key)
if(GLOB.do_after_once_tracker[cache_key] && GLOB.do_after_once_tracker[cache_key] == DOAFTERONCE_MAGIC)
GLOB.do_after_once_tracker[cache_key] = FALSE
- return FALSE
- return TRUE
+ return TRUE
+ return FALSE
/proc/is_species(A, species_datum)
. = FALSE
@@ -573,7 +585,8 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
LogMouseMacro(".mouse", params)
/proc/update_all_mob_security_hud()
- for(var/mob/living/carbon/human/H in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
H.sec_hud_set_security_status()
/proc/getviewsize(view)
@@ -610,3 +623,34 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
chosen = pick(mob_spawn_meancritters)
var/mob/living/simple_animal/C = new chosen(spawn_location)
return C
+
+//determines the job of a mob, taking into account job transfers
+/proc/determine_role(mob/living/P)
+ var/datum/mind/M = P.mind
+ if(!M)
+ return
+ return M.playtime_role ? M.playtime_role : M.assigned_role //returns current role
+
+/** checks the security force on station and returns a list of numbers, of the form:
+ * total, active, dead, antag
+ * where active is defined as conscious (STAT = 0) and not an antag
+*/
+/proc/check_active_security_force()
+ var/sec_positions = GLOB.security_positions - "Magistrate" - "Brig Physician"
+ var/total = 0
+ var/active = 0
+ var/dead = 0
+ var/antag = 0
+ for(var/p in GLOB.human_list) //contains only human mobs, so no type check needed
+ var/mob/living/carbon/human/player = p //need to tell it what type it is or we can't access stat without the dreaded :
+ if(determine_role(player) in sec_positions)
+ total++
+ if(player.stat == DEAD)
+ dead++
+ continue
+ if(isAntag(player))
+ antag++
+ continue
+ if(player.stat == CONSCIOUS)
+ active++
+ return list(total, active, dead, antag)
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index d702c073b86..29e0f9b52b9 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -19,10 +19,10 @@ GLOBAL_VAR(command_name)
/proc/command_name()
return GLOB.using_map.dock_name
-var/religion_name = null
+GLOBAL_VAR(religion_name)
/proc/religion_name()
- if(religion_name)
- return religion_name
+ if(GLOB.religion_name)
+ return GLOB.religion_name
var/name = ""
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index ecbebf813df..47650177283 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -533,7 +533,7 @@ proc/checkhtml(var/t)
text = replacetext(text, "\[/grid\]", "")
text = replacetext(text, "\[row\]", "
")
text = replacetext(text, "\[cell\]", "
")
- text = replacetext(text, "\[logo\]", "")
+ text = replacetext(text, "\[logo\]", "​")
text = replacetext(text, "\[time\]", "[station_time_timestamp()]") // TO DO
if(!no_font)
if(P)
diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm
index 340d7a3b134..83347c20d3b 100644
--- a/code/__HELPERS/time.dm
+++ b/code/__HELPERS/time.dm
@@ -11,25 +11,6 @@
#define TICKS2DS(T) ((T) TICKS)
-#define TimeOfGame (get_game_time())
-#define TimeOfTick (world.tick_usage*0.01*world.tick_lag)
-
-/proc/get_game_time()
- var/global/time_offset = 0
- var/global/last_time = 0
- var/global/last_usage = 0
-
- var/wtime = world.time
- var/wusage = world.tick_usage * 0.01
-
- if(last_time < wtime && last_usage > 1)
- time_offset += last_usage - 1
-
- last_time = wtime
- last_usage = wusage
-
- return wtime + (time_offset + wusage) * world.tick_lag
-
/* This proc should only be used for world/Topic.
* If you want to display the time for which dream daemon has been running ("round time") use worldtime2text.
* If you want to display the canonical station "time" (aka the in-character time of the station) use station_time_timestamp
@@ -98,14 +79,14 @@ proc/isDay(var/month, var/day)
* Returns "watch handle" (really just a timestamp :V)
*/
/proc/start_watch()
- return TimeOfGame
+ return REALTIMEOFDAY
/**
* Returns number of seconds elapsed.
* @param wh number The "Watch Handle" from start_watch(). (timestamp)
*/
/proc/stop_watch(wh)
- return round(0.1 * (TimeOfGame - wh), 0.1)
+ return round(0.1 * (REALTIMEOFDAY - wh), 0.1)
/proc/numberToMonthName(number)
return GLOB.month_names.Find(number)
diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm
index 467b07a0ddf..352a6fa3680 100644
--- a/code/__HELPERS/traits.dm
+++ b/code/__HELPERS/traits.dm
@@ -62,7 +62,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
//mob traits
#define TRAIT_PACIFISM "pacifism"
-#define TRAIT_WATERBREATH "waterbreathing"
+#define TRAIT_WATERBREATH "waterbreathing"
+#define TRAIT_BLOODCRAWL "bloodcrawl"
+#define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat"
+#define TRAIT_JESTER "jester"
// common trait sources
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 661d09f0412..bf44f6a4bc9 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -167,7 +167,7 @@
return SOUTH
if(225.6 to 315.5)
return WEST
-
+
//returns the north-zero clockwise angle in degrees, given a direction
/proc/dir2angle(var/D)
@@ -212,6 +212,7 @@
if(rights & R_PROCCALL) . += "[seperator]+PROCCALL"
if(rights & R_MOD) . += "[seperator]+MODERATOR"
if(rights & R_MENTOR) . += "[seperator]+MENTOR"
+ if(rights & R_VIEWRUNTIMES) . += "[seperator]+VIEWRUNTIMES"
return .
/proc/ui_style2icon(ui_style)
diff --git a/code/__HELPERS/unique_ids.dm b/code/__HELPERS/unique_ids.dm
index 549f5c71016..b66b1a11b90 100644
--- a/code/__HELPERS/unique_ids.dm
+++ b/code/__HELPERS/unique_ids.dm
@@ -16,8 +16,6 @@
GLOBAL_VAR_INIT(next_unique_datum_id, 1)
-// /client/var/tmp/unique_datum_id = null
-
/datum/proc/UID()
if(!unique_datum_id)
var/tag_backup = tag
@@ -37,8 +35,6 @@ GLOBAL_VAR_INIT(next_unique_datum_id, 1)
var/datum/D = locate(copytext(uid, 1, splitat))
- // We might locate a client instead of a datum, but just using : is easier
- // than actually checking and typecasting
- if(D && D:unique_datum_id == uid)
+ if(D && D.unique_datum_id == uid)
return D
return null
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index aedc16c4162..7e57a394988 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -25,11 +25,9 @@
if(!( istext(HTMLstring) ))
CRASH("Given non-text argument!")
- return
else
if(length(HTMLstring) != 7)
CRASH("Given non-HTML argument!")
- return
var/textr = copytext(HTMLstring, 2, 4)
var/textg = copytext(HTMLstring, 4, 6)
var/textb = copytext(HTMLstring, 6, 8)
@@ -46,7 +44,6 @@
if(length(textb) < 2)
textr = text("0[]", textb)
return text("#[][][]", textr, textg, textb)
- return
//Returns the middle-most value
/proc/dd_range(var/low, var/high, var/num)
@@ -320,7 +317,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
//When a borg is activated, it can choose which AI it wants to be slaved to
/proc/active_ais()
. = list()
- for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
if(A.stat == DEAD)
continue
if(A.control_disabled == 1)
@@ -332,8 +329,9 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/select_active_ai_with_fewest_borgs()
var/mob/living/silicon/ai/selected
var/list/active = active_ais()
- for(var/mob/living/silicon/ai/A in active)
- if(!selected || (selected.connected_robots > A.connected_robots))
+ for(var/thing in active)
+ var/mob/living/silicon/ai/A = thing
+ if(!selected || (length(selected.connected_robots) > length(A.connected_robots)))
selected = A
return selected
@@ -437,16 +435,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
return "[round((powerused * 0.000001), 0.001)] MW"
return "[round((powerused * 0.000000001), 0.0001)] GW"
-//E = MC^2
-/proc/convert2energy(var/M)
- var/E = M*(SPEED_OF_LIGHT_SQ)
- return E
-
-//M = E/C^2
-/proc/convert2mass(var/E)
- var/M = E/(SPEED_OF_LIGHT_SQ)
- return M
-
//Forces a variable to be posative
/proc/modulus(var/M)
if(M >= 0)
@@ -540,21 +528,6 @@ Returns 1 if the chain up to the area contains the given typepath
/proc/between(var/low, var/middle, var/high)
return max(min(middle, high), low)
-
-
-#if DM_VERSION > 513
-#warn 513 is definitely stable now, remove this
-#endif
-#if DM_VERSION < 513
-/proc/arctan(x)
- var/y=arcsin(x/sqrt(1+x*x))
- return y
-/proc/islist(list/list)
- if(istype(list))
- return 1
- return 0
-#endif
-
//returns random gauss number
proc/GaussRand(var/sigma)
var/x,y,rsq
@@ -1520,7 +1493,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
//orbit() can run without it (swap orbiting for A)
//but then you can never stop it and that's just silly.
/atom/movable/var/atom/orbiting = null
-
+/atom/movable/var/cached_transform = null
//A: atom to orbit
//radius: range to orbit at, radius of the circle formed by orbiting
//clockwise: whether you orbit clockwise or anti clockwise
@@ -1538,6 +1511,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
orbiting = A
var/matrix/initial_transform = matrix(transform)
+ cached_transform = initial_transform
var/lastloc = loc
//Head first!
@@ -1555,8 +1529,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
- //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
- transform = initial_transform
while(orbiting && orbiting == A && A.loc)
var/targetloc = get_turf(A)
if(!lockinorbit && loc != lastloc && loc != targetloc)
@@ -1570,12 +1542,14 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
if(orbiting == A) //make sure we haven't started orbiting something else.
orbiting = null
- SpinAnimation(0,0)
+ SpinAnimation(0, 0)
+ transform = cached_transform
/atom/movable/proc/stop_orbit()
orbiting = null
+ transform = cached_transform
//Centers an image.
//Requires:
@@ -1813,7 +1787,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/obj/machinery/portable_atmospherics/canister = "CANISTER",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/machinery/power = "POWER",
- /obj/machinery/telecomms = "TCOMMS",
/obj/machinery = "MACHINERY",
/obj/mecha = "MECHA",
/obj/structure/closet/crate = "CRATE",
@@ -2036,6 +2009,13 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
tX = splittext(tX[1], ":")
tX = tX[1]
var/list/actual_view = getviewsize(C ? C.view : world.view)
- tX = Clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx)
- tY = Clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy)
+ tX = clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx)
+ tY = clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy)
return locate(tX, tY, tZ)
+
+/proc/CallAsync(datum/source, proctype, list/arguments)
+ set waitfor = FALSE
+ return call(source, proctype)(arglist(arguments))
+
+/// Waits at a line of code until X is true
+#define UNTIL(X) while(!(X)) stoplag()
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index bd7e6484bdf..342e572177a 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -1,6 +1,14 @@
#define DEBUG
//#define TESTING
+// Uncomment the following line to compile unit tests.
+// #define UNIT_TESTS
+
+
+#ifdef TRAVISBUILDING
+#define UNIT_TESTS
+#endif
+
#ifdef TESTING
//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing.
//implies FIND_REF_NO_CHECK_TICK
@@ -11,8 +19,6 @@
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
-#define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary.
-
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
#define MAX_MESSAGE_LEN 1024
#define MAX_PAPER_MESSAGE_LEN 3072
@@ -20,12 +26,14 @@
#define MAX_BOOK_MESSAGE_LEN 9216
#define MAX_NAME_LEN 50 //diona names can get loooooooong
-// Version check, terminates compilation if someone is using a version of BYOND that's too old
-#if DM_VERSION < 510
-#error OUTDATED VERSION ERROR - \
-Due to BYOND features used in this codebase, you must update to version 510 or later to compile. \
-This may require updating to a beta release.
+//Update this whenever you need to take advantage of more recent byond features
+#define MIN_COMPILER_VERSION 513
+#define MIN_COMPILER_BUILD 1514
+#if DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD
+//Don't forget to update this part
+#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
+#error You need version 513.1514 or higher
#endif
// Macros that must exist before world.dm
-#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
+// #define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm
index 5cf36541eeb..ea2cf1290fd 100644
--- a/code/_globalvars/configuration.dm
+++ b/code/_globalvars/configuration.dm
@@ -4,7 +4,6 @@ GLOBAL_VAR(host)
GLOBAL_VAR(join_motd)
GLOBAL_VAR(join_tos)
GLOBAL_VAR_INIT(game_version, "ParaCode")
-GLOBAL_VAR_INIT(changelog_hash, md5('html/changelog.html')) //used to check if the CL changed
GLOBAL_VAR_INIT(game_year, (text2num(time2text(world.realtime, "YYYY")) + 544))
GLOBAL_VAR_INIT(aliens_allowed, 1)
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index b6fcae25061..17444f66207 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -3,30 +3,33 @@ GLOBAL_LIST_EMPTY(all_species)
GLOBAL_LIST_EMPTY(all_languages)
GLOBAL_LIST_EMPTY(language_keys) // Table of say codes for all languages
GLOBAL_LIST_EMPTY(all_superheroes)
-GLOBAL_LIST_INIT(whitelisted_species, list())
+GLOBAL_LIST_EMPTY(whitelisted_species)
-GLOBAL_LIST_INIT(clients, list()) //list of all clients
-GLOBAL_LIST_INIT(admins, list()) //list of all clients whom are admins
-GLOBAL_LIST_INIT(deadmins, list()) //list of all clients who have used the de-admin verb.
-GLOBAL_LIST_INIT(directory, list()) //list of all ckeys with associated client
-GLOBAL_LIST_INIT(stealthminID, list()) //reference list with IDs that store ckeys, for stealthmins
+GLOBAL_LIST_EMPTY(clients) //list of all clients
+GLOBAL_LIST_EMPTY(admins) //list of all clients whom are admins
+GLOBAL_LIST_EMPTY(deadmins) //list of all clients who have used the de-admin verb.
+GLOBAL_LIST_EMPTY(directory) //list of all ckeys with associated client
+GLOBAL_LIST_EMPTY(stealthminID) //reference list with IDs that store ckeys, for stealthmins
//Since it didn't really belong in any other category, I'm putting this here
//This is for procs to replace all the goddamn 'in world's that are chilling around the code
-GLOBAL_LIST_INIT(player_list, list()) //List of all mobs **with clients attached**. Excludes /mob/new_player
-GLOBAL_LIST_INIT(mob_list, list()) //List of all mobs, including clientless
-GLOBAL_LIST_INIT(silicon_mob_list, list()) //List of all silicon mobs, including clientless
-GLOBAL_LIST_INIT(spirits, list()) //List of all the spirits, including Masks
-GLOBAL_LIST_INIT(living_mob_list, list()) //List of all alive mobs, including clientless. Excludes /mob/new_player
-GLOBAL_LIST_INIT(dead_mob_list, list()) //List of all dead mobs, including clientless. Excludes /mob/new_player
-GLOBAL_LIST_INIT(respawnable_list, list()) //List of all mobs, dead or in mindless creatures that still be respawned.
-GLOBAL_LIST_INIT(non_respawnable_keys, list()) //List of ckeys that are excluded from respawning for remainder of round.
+GLOBAL_LIST_EMPTY(player_list) //List of all mobs **with clients attached**. Excludes /mob/new_player
+GLOBAL_LIST_EMPTY(mob_list) //List of all mobs, including clientless
+GLOBAL_LIST_EMPTY(silicon_mob_list) //List of all silicon mobs, including clientless
+GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes
+GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain simple animals
+GLOBAL_LIST_EMPTY(human_list) //all instances of /mob/living/carbon/human and subtypes
+GLOBAL_LIST_EMPTY(spirits) //List of all the spirits, including Masks
+GLOBAL_LIST_EMPTY(alive_mob_list) //List of all alive mobs, including clientless. Excludes /mob/new_player
+GLOBAL_LIST_EMPTY(dead_mob_list) //List of all dead mobs, including clientless. Excludes /mob/new_player
+GLOBAL_LIST_EMPTY(respawnable_list) //List of all mobs, dead or in mindless creatures that still be respawned.
+GLOBAL_LIST_EMPTY(non_respawnable_keys) //List of ckeys that are excluded from respawning for remainder of round.
GLOBAL_LIST_INIT(simple_animals, list(list(), list(), list(), list())) //One for each AI_* status define, List of all simple animals, including clientless
-GLOBAL_LIST_INIT(bots_list, list()) //List of all bots(beepsky, medibots,etc)
+GLOBAL_LIST_EMPTY(bots_list) //List of all bots(beepsky, medibots,etc)
-GLOBAL_LIST_INIT(med_hud_users, list())
-GLOBAL_LIST_INIT(sec_hud_users, list())
-GLOBAL_LIST_INIT(antag_hud_users, list())
-GLOBAL_LIST_INIT(surgeries_list, list())
-GLOBAL_LIST_INIT(hear_radio_list, list()) //Mobs that hear the radio even if there's no client
+GLOBAL_LIST_EMPTY(med_hud_users)
+GLOBAL_LIST_EMPTY(sec_hud_users)
+GLOBAL_LIST_EMPTY(antag_hud_users)
+GLOBAL_LIST_EMPTY(surgeries_list)
+GLOBAL_LIST_EMPTY(hear_radio_list) //Mobs that hear the radio even if there's no client
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 931a0e394e8..21af95cab48 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -16,7 +16,6 @@ GLOBAL_LIST_INIT(prisoncomputer_list, list())
GLOBAL_LIST_INIT(celltimers_list, list()) // list of all cell timers
GLOBAL_LIST_INIT(cell_logs, list())
GLOBAL_LIST_INIT(navigation_computers, list())
-GLOBAL_LIST_INIT(zombie_infection_list, list())
GLOBAL_LIST_INIT(all_areas, list())
GLOBAL_LIST_INIT(machines, list())
diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm
index 20620d60800..abd878ff936 100644
--- a/code/_globalvars/lists/reagents.dm
+++ b/code/_globalvars/lists/reagents.dm
@@ -64,3 +64,5 @@ GLOBAL_LIST_INIT(safe_chem_list, list("antihol", "charcoal", "epinephrine", "ins
"omnizine", "stimulants", "synaptizine", "potass_iodide", "oculine", "mannitol", "styptic_powder",
"spaceacillin", "salglu_solution", "sal_acid", "cryoxadone", "blood", "synthflesh", "hydrocodone",
"mitocholide", "rezadone"))
+
+GLOBAL_LIST_INIT(safe_chem_applicator_list, list("silver_sulfadiazine", "styptic_powder", "synthflesh"))
diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm
index 631d356af0b..50e70bc62a4 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -15,6 +15,8 @@ GLOBAL_VAR(world_asset_log)
GLOBAL_PROTECT(world_asset_log)
GLOBAL_VAR(runtime_summary_log)
GLOBAL_PROTECT(runtime_summary_log)
+GLOBAL_VAR(tgui_log)
+GLOBAL_PROTECT(tgui_log)
GLOBAL_LIST_EMPTY(jobMax)
GLOBAL_PROTECT(jobMax)
diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm
index ca1c899e301..e43062a18b7 100644
--- a/code/_globalvars/mapping.dm
+++ b/code/_globalvars/mapping.dm
@@ -3,8 +3,9 @@
#define Z_SOUTH 3
#define Z_WEST 4
-GLOBAL_LIST_INIT(cardinal, list( NORTH, SOUTH, EAST, WEST ))
+GLOBAL_LIST_INIT(cardinal, list(NORTH, SOUTH, EAST, WEST))
GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
+GLOBAL_LIST_INIT(alldirs2, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTH, SOUTH, EAST, WEST))
GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
// This must exist early on or shit breaks bad
@@ -54,3 +55,7 @@ GLOBAL_LIST_EMPTY(space_ruins_templates)
GLOBAL_LIST_EMPTY(lava_ruins_templates)
GLOBAL_LIST_EMPTY(shelter_templates)
GLOBAL_LIST_EMPTY(shuttle_templates)
+
+// Teleport locations
+GLOBAL_LIST_EMPTY(teleportlocs)
+GLOBAL_LIST_EMPTY(ghostteleportlocs)
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index 32d6370f3d0..283d92a954f 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -4,7 +4,7 @@ GLOBAL_DATUM(slmaster, /obj/effect/overlay)
GLOBAL_VAR_INIT(CELLRATE, 0.002) // conversion ratio between a watt-tick and kilojoule
GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)
-// Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it.
+// Announcer intercom, because too much stuff creates an intercom for one message then qdel()s it.
GLOBAL_DATUM_INIT(global_announcer, /obj/item/radio/intercom, create_global_announcer())
GLOBAL_DATUM_INIT(command_announcer, /obj/item/radio/intercom/command, create_command_announcer())
@@ -89,7 +89,7 @@ GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE)
GLOBAL_VAR(map_name) // Self explanatory
-GLOBAL_DATUM(data_core, /datum/datacore) // Station datacore, manifest, etc
+GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc
GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled
@@ -101,3 +101,4 @@ GLOBAL_PROTECT(dbcon)
GLOBAL_LIST_EMPTY(ability_verbs) // Create-level abilities
GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE))
+
diff --git a/code/_globalvars/sensitive.dm b/code/_globalvars/sensitive.dm
index b1e6751c4dd..4c04b2d480b 100644
--- a/code/_globalvars/sensitive.dm
+++ b/code/_globalvars/sensitive.dm
@@ -9,4 +9,4 @@ GLOBAL_REAL_VAR(sqlfdbkdb) = "test"
GLOBAL_REAL_VAR(sqlfdbklogin) = "root"
GLOBAL_REAL_VAR(sqlfdbkpass) = ""
GLOBAL_REAL_VAR(sqlfdbktableprefix) = "erro_"
-
+GLOBAL_REAL_VAR(sql_version) = 0
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index 9e0d45643be..ccc31e5c501 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -5,7 +5,10 @@
*/
GLOBAL_LIST_INIT(traits_by_type, list(
/mob = list(
- "TRAIT_PACIFISM" = TRAIT_PACIFISM
+ "TRAIT_PACIFISM" = TRAIT_PACIFISM,
+ "TRAIT_WATERBREATH" = TRAIT_WATERBREATH,
+ "BLOODCRAWL" = TRAIT_BLOODCRAWL,
+ "BLOODCRAWL_EAT" = TRAIT_BLOODCRAWL_EAT
)))
/// value -> trait name, generated on use from trait_by_type global
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 6bfd72413de..d840f64bb4a 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -134,9 +134,9 @@
if(W == A)
W.attack_self(src)
if(hand)
- update_inv_l_hand(0)
+ update_inv_l_hand()
else
- update_inv_r_hand(0)
+ update_inv_r_hand()
return
// operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper)
@@ -258,28 +258,34 @@
Makes the mob face the direction of the clicked thing
*/
/mob/proc/MiddleShiftClickOn(atom/A)
+ return
+
+/mob/living/MiddleShiftClickOn(atom/A)
if(incapacitated())
return
var/face_dir = get_cardinal_dir(src, A)
- if(forced_look == face_dir)
+ if(!face_dir || forced_look == face_dir || A == src)
forced_look = null
- to_chat(src, "You are no longer facing any direction.")
+ to_chat(src, "Cancelled direction lock.")
return
forced_look = face_dir
- to_chat(src, "You are now facing [dir2text(forced_look)].")
+ to_chat(src, "You are now facing [dir2text(forced_look)]. To cancel this, shift-middleclick yourself.")
/*
Middle shift-control-click
Makes the mob constantly face the object (until it's out of sight)
*/
/mob/proc/MiddleShiftControlClickOn(atom/A)
+ return
+
+/mob/living/MiddleShiftControlClickOn(atom/A)
var/face_uid = A.UID()
- if(forced_look == face_uid)
+ if(forced_look == face_uid || A == src)
forced_look = null
- to_chat(src, "You are no longer facing [A].")
+ to_chat(src, "Cancelled direction lock.")
return
forced_look = face_uid
- to_chat(src, "You are now facing [A].")
+ to_chat(src, "You are now facing [A]. To cancel this, shift-middleclick yourself.")
// In case of use break glass
/*
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 58e82733abe..b069ff31eb7 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -161,10 +161,13 @@
#define ui_bot_pull "EAST-2:26,SOUTH:7"
//Ghosts
-#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
-#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
-#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
-#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
+#define ui_ghost_jumptomob "SOUTH:6,CENTER-2"
+#define ui_ghost_orbit "SOUTH:6,CENTER-1"
+#define ui_ghost_reenter_corpse "SOUTH:6,CENTER"
+#define ui_ghost_teleport "SOUTH:6,CENTER+1"
+#define ui_ghost_respawn_list "SOUTH:6,CENTER+2"
+#define ui_ghost_respawn_mob "SOUTH:6+1,CENTER+2"
+#define ui_ghost_respawn_pai "SOUTH:6+2,CENTER+2"
//HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12.
#define HUD_STYLE_STANDARD 1
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index d49c0ee59eb..a93e65c762b 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -19,9 +19,8 @@
if(!category)
return
- var/obj/screen/alert/alert
- if(alerts[category])
- alert = alerts[category]
+ var/obj/screen/alert/alert = LAZYACCESS(alerts, category)
+ if(alert)
if(alert.override_alerts)
return 0
if(new_master && new_master != alert.master)
@@ -57,7 +56,7 @@
alert.icon_state = "[initial(alert.icon_state)][severity]"
alert.severity = severity
- alerts[category] = alert
+ LAZYSET(alerts, category, alert) // This also creates the list if it doesn't exist
if(client && hud_used)
hud_used.reorganize_alerts()
alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
@@ -72,7 +71,7 @@
// Proc to clear an existing alert.
/mob/proc/clear_alert(category, clear_override = FALSE)
- var/obj/screen/alert/alert = alerts[category]
+ var/obj/screen/alert/alert = LAZYACCESS(alerts, category)
if(!alert)
return 0
if(alert.override_alerts && !clear_override)
@@ -585,12 +584,14 @@ so as to remain in compliance with the most up-to-date laws."
// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
/datum/hud/proc/reorganize_alerts()
var/list/alerts = mymob.alerts
+ if(!alerts)
+ return FALSE
var/icon_pref
if(!hud_shown)
- for(var/i = 1, i <= alerts.len, i++)
+ for(var/i in 1 to alerts.len)
mymob.client.screen -= alerts[alerts[i]]
- return 1
- for(var/i = 1, i <= alerts.len, i++)
+ return TRUE
+ for(var/i in 1 to alerts.len)
var/obj/screen/alert/alert = alerts[alerts[i]]
if(alert.icon_state == "template")
if(!icon_pref)
@@ -611,10 +612,10 @@ so as to remain in compliance with the most up-to-date laws."
. = ""
alert.screen_loc = .
mymob.client.screen |= alert
- return 1
+ return TRUE
/mob
- var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
+ var/list/alerts // lazy list. contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
/obj/screen/alert/Click(location, control, params)
if(!usr || !usr.client)
diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm
index 600c1105e8e..a291120fb85 100644
--- a/code/_onclick/hud/ghost.dm
+++ b/code/_onclick/hud/ghost.dm
@@ -40,6 +40,52 @@
var/mob/dead/observer/G = usr
G.dead_tele()
+/obj/screen/ghost/respawn_list
+ name = "Ghost spawns"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "template"
+
+/obj/screen/ghost/respawn_list/Initialize(mapload)
+ . = ..()
+ update_hidden_state()
+
+/obj/screen/ghost/respawn_list/Click()
+ var/client/C = hud.mymob.client
+ hud.inventory_shown = !hud.inventory_shown
+ if(hud.inventory_shown)
+ C.screen += hud.toggleable_inventory
+ else
+ C.screen -= hud.toggleable_inventory
+ update_hidden_state()
+
+/obj/screen/ghost/respawn_list/proc/update_hidden_state()
+ var/matrix/M = matrix(transform)
+ M.Turn(-90)
+
+ overlays.Cut()
+ var/image/img = image('icons/mob/actions/actions.dmi', src, (hud && hud.inventory_shown) ? "hide" : "show")
+ img.transform = M
+ overlays += img
+
+/obj/screen/ghost/respawn_mob
+ name = "Mob spawners"
+ icon_state = "mob_spawner"
+
+/obj/screen/ghost/respawn_mob/Click()
+ var/mob/dead/observer/G = usr
+ G.open_spawners_menu()
+
+/obj/screen/ghost/respawn_pai
+ name = "Configure pAI"
+ icon_state = "pai"
+
+/obj/screen/ghost/respawn_pai/Click()
+ var/mob/dead/observer/G = usr
+ GLOB.paiController.recruitWindow(G)
+
+/datum/hud/ghost
+ inventory_shown = FALSE
+
/datum/hud/ghost/New(mob/owner)
..()
var/obj/screen/using
@@ -59,6 +105,22 @@
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
static_inventory += using
+ static_inventory += using
+
+ using = new /obj/screen/ghost/respawn_list()
+ using.screen_loc = ui_ghost_respawn_list
+ static_inventory += using
+
+ using = new /obj/screen/ghost/respawn_mob()
+ using.screen_loc = ui_ghost_respawn_mob
+ toggleable_inventory += using
+
+ using = new /obj/screen/ghost/respawn_pai()
+ using.screen_loc = ui_ghost_respawn_pai
+ toggleable_inventory += using
+
+ for(var/obj/screen/S in (static_inventory + toggleable_inventory))
+ S.hud = src
/datum/hud/ghost/show_hud()
mymob.client.screen = list()
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index f03d436bcaf..8f243dfcdc1 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -3,6 +3,10 @@
/datum/hud/simple_animal/New(mob/user)
..()
+
+ mymob.healths = new /obj/screen/healths()
+ infodisplay += mymob.healths
+
var/obj/screen/using
using = new /obj/screen/act_intent/simple_animal()
using.icon_state = mymob.a_intent
diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm
index 68847cbd97d..d5fb5cad4fa 100644
--- a/code/_onclick/hud/parallax.dm
+++ b/code/_onclick/hud/parallax.dm
@@ -246,7 +246,7 @@
if(!view)
view = world.view
var/list/new_overlays = list()
- var/count = Ceiling(view/(480/world.icon_size))+1
+ var/count = CEILING(view/(480/world.icon_size), 1)+1
for(var/x in -count to count)
for(var/y in -count to count)
if(x == 0 && y == 0)
diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm
index 872659d714b..eda0cc5640d 100644
--- a/code/_onclick/hud/picture_in_picture.dm
+++ b/code/_onclick/hud/picture_in_picture.dm
@@ -102,8 +102,8 @@
overlays += standard_background
/obj/screen/movable/pic_in_pic/proc/set_view_size(width, height, do_refresh = TRUE)
- width = Clamp(width, 0, max_dimensions)
- height = Clamp(height, 0, max_dimensions)
+ width = clamp(width, 0, max_dimensions)
+ height = clamp(height, 0, max_dimensions)
src.width = width
src.height = height
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index 14080274617..f048c3c393d 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -201,7 +201,7 @@
if(!R.robot_modules_background)
return
- var/display_rows = Ceiling(R.module.modules.len / 8)
+ var/display_rows = CEILING(R.module.modules.len / 8, 1)
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
R.client.screen += R.robot_modules_background
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index c0f5cfd5f3b..1423720f8f6 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -371,15 +371,15 @@
return 1
if(istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
return 1
-
+
if(hud?.mymob && slot_id)
var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
if(inv_item)
return inv_item.Click(location, control, params)
if(usr.attack_ui(slot_id))
- usr.update_inv_l_hand(0)
- usr.update_inv_r_hand(0)
+ usr.update_inv_l_hand()
+ usr.update_inv_r_hand()
return 1
/obj/screen/inventory/hand
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index cc0269cdc95..4fd5b956df5 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -58,7 +58,7 @@
else
return 1
var/obj/item/organ/external/O = M.get_organ(user.zone_selected)
- if((is_sharp(src) || (isscrewdriver(src) && O.is_robotic())) && user.a_intent == INTENT_HELP)
+ if((is_sharp(src) || (isscrewdriver(src) && O?.is_robotic())) && user.a_intent == INTENT_HELP)
if(!attempt_initiate_surgery(src, M, user))
return FALSE
else
@@ -75,8 +75,8 @@
if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
- user.lastattacked = M
- M.lastattacker = user
+ M.lastattacker = user.real_name
+ M.lastattackerckey = user.ckey
user.do_attack_animation(M)
. = M.attacked_by(src, user, def_zone)
@@ -135,9 +135,9 @@
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
- return Clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
+ return clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
else
- return Clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
+ return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
if(I.discrete)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 460bc0193f6..3452400edbb 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -15,7 +15,6 @@
// Otherwise jump
else
- following = null
forceMove(get_turf(A))
update_parallax_contents()
@@ -64,7 +63,7 @@
if(!istype(user)) // Make sure user is actually an observer. Revenents also use attack_ghost, but do not have the health_scan var.
return
if(user.client && user.health_scan)
- if(issilicon(src) || ismachine(src))
+ if(issilicon(src) || ismachineperson(src))
robot_healthscan(user, src)
else if(ishuman(src))
healthscan(user, src, 1, TRUE)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 2f4811de380..756ce6f8527 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -36,7 +36,7 @@
var/vote_no_default = 0 // vote does not default to nochange/norestart (tbi)
var/vote_no_dead = 0 // dead people can't vote (tbi)
// var/enable_authentication = 0 // goon authentication
- var/del_new_on_log = 1 // del's new players if they log before they spawn in
+ var/del_new_on_log = 1 // qdel's new players if they log before they spawn in
var/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
var/traitor_scaling = 0 //if amount of traitors scales based on amount of players
var/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other
@@ -61,7 +61,6 @@
var/usewhitelist = 0
var/mods_are_mentors = 0
var/load_jobs_from_txt = 0
- var/ToRban = 0
var/automute_on = 0 //enables automuting/spam prevention
var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
var/round_abandon_penalty_period = 30 MINUTES // Time from round start during which ghosting out is penalized
@@ -200,8 +199,8 @@
var/disable_away_missions = 0 // disable away missions
var/disable_space_ruins = 0 //disable space ruins
- var/extra_space_ruin_levels_min = 2
- var/extra_space_ruin_levels_max = 4
+ var/extra_space_ruin_levels_min = 4
+ var/extra_space_ruin_levels_max = 8
var/ooc_allowed = 1
var/looc_allowed = 1
@@ -265,6 +264,11 @@
src.votable_modes += "secret"
/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Config reload blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to reload configuration via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to reload configuration via advanced proc-call")
+ return
var/list/Lines = file2list(filename)
for(var/t in Lines)
@@ -573,9 +577,6 @@
if("humans_need_surnames")
humans_need_surnames = 1
- if("tor_ban")
- ToRban = 1
-
if("automute_on")
automute_on = 1
@@ -641,31 +642,31 @@
config.max_maint_drones = text2num(value)
if("expected_round_length")
- config.expected_round_length = MinutesToTicks(text2num(value))
+ config.expected_round_length = text2num(value) MINUTES
if("event_custom_start_mundane")
var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+ config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_custom_start_moderate")
var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+ config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_custom_start_major")
var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
+ config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_delay_lower")
var/values = text2numlist(value, ";")
- config.event_delay_lower[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_lower[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_lower[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
+ config.event_delay_lower[EVENT_LEVEL_MUNDANE] = values[1] MINUTES
+ config.event_delay_lower[EVENT_LEVEL_MODERATE] = values[2] MINUTES
+ config.event_delay_lower[EVENT_LEVEL_MAJOR] = values[3] MINUTES
if("event_delay_upper")
var/values = text2numlist(value, ";")
- config.event_delay_upper[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_upper[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_upper[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
+ config.event_delay_upper[EVENT_LEVEL_MUNDANE] = values[1] MINUTES
+ config.event_delay_upper[EVENT_LEVEL_MODERATE] = values[2] MINUTES
+ config.event_delay_upper[EVENT_LEVEL_MAJOR] = values[3] MINUTES
if("starlight")
config.starlight = 1
@@ -701,7 +702,7 @@
config.max_loadout_points = text2num(value)
if("round_abandon_penalty_period")
- config.round_abandon_penalty_period = MinutesToTicks(text2num(value))
+ config.round_abandon_penalty_period = text2num(value) MINUTES
if("medal_hub_address")
config.medal_hub_address = value
@@ -808,8 +809,12 @@
log_config("Unknown setting in configuration: '[name]'")
/datum/configuration/proc/loadsql(filename) // -- TLE
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "SQL configuration reload blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to reload SQL configuration via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to reload SQL configuration via advanced proc-call")
+ return
var/list/Lines = file2list(filename)
- var/db_version = 0
for(var/t in Lines)
if(!t) continue
@@ -848,10 +853,13 @@
if("feedback_tableprefix")
sqlfdbktableprefix = value
if("db_version")
- db_version = text2num(value)
+ sql_version = text2num(value)
else
log_config("Unknown setting in configuration: '[name]'")
- if(config.sql_enabled && db_version != SQL_VERSION)
+
+ // The unit tests have their own version of this check, which wont hold the server up infinitely, so this is disabled if we are running unit tests
+ #ifndef UNIT_TESTS
+ if(config.sql_enabled && sql_version != SQL_VERSION)
config.sql_enabled = 0
log_config("WARNING: DB_CONFIG DEFINITION MISMATCH!")
spawn(60)
@@ -859,6 +867,7 @@
SSticker.ticker_going = FALSE
spawn(600)
to_chat(world, "DB_CONFIG MISMATCH, ROUND START DELAYED. Please check database version for recent upstream changes!")
+ #endif
/datum/configuration/proc/loadoverflowwhitelist(filename)
var/list/Lines = file2list(filename)
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index 5a520b547e1..691f19201f6 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -14,7 +14,7 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
var/datum/controller/exclude_these = new
gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order")
- qdel(exclude_these)
+ QDEL_IN(exclude_these, 0) //signal logging isn't ready
Initialize()
diff --git a/code/controllers/hooks-defs.dm b/code/controllers/hooks-defs.dm
deleted file mode 100644
index 59510162e1c..00000000000
--- a/code/controllers/hooks-defs.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Startup hook.
- * Called in world.dm when the server starts.
- */
-/hook/startup
-
-/**
- * Roundstart hook.
- * Called in gameticker.dm when a round starts.
- */
-/hook/roundstart
diff --git a/code/controllers/hooks.dm b/code/controllers/hooks.dm
deleted file mode 100644
index 48f1199ef76..00000000000
--- a/code/controllers/hooks.dm
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * @file hooks.dm
- * Implements hooks, a simple way to run code on pre-defined events.
- */
-
-/** @page hooks Code hooks
- * @section hooks Hooks
- * A hook is defined under /hook in the type tree.
- *
- * To add some code to be called by the hook, define a proc under the type, as so:
- * @code
- /hook/foo/proc/bar()
- if(1)
- return 1 //Sucessful
- else
- return 0 //Error, or runtime.
- * @endcode
- * All hooks must return nonzero on success, as runtimes will force return null.
- */
-
-/**
- * Calls a hook, executing every piece of code that's attached to it.
- * @param hook Identifier of the hook to call.
- * @returns 1 if all hooked code runs successfully, 0 otherwise.
- */
-/proc/callHook(hook, list/args=null)
- var/hook_path = text2path("/hook/[hook]")
- if(!hook_path)
- error("Invalid hook '/hook/[hook]' called.")
- return 0
-
- var/caller = new hook_path
- var/status = 1
- for(var/P in typesof("[hook_path]/proc"))
- if(!call(caller, P)(arglist(args)))
- error("Hook '[P]' failed or runtimed.")
- status = 0
-
- return status
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index f64e566e097..b8c3cdbf1e2 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -62,10 +62,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/static/current_ticklimit = TICK_LIMIT_RUNNING
/datum/controller/master/New()
- //temporary file used to record errors with loading config, moved to log directory once logging is set up
- GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = "data/logs/config_error.log"
- load_configuration()
- // Highlander-style: there can only be one! Kill off the old and replace it with the new.
if(!random_seed)
random_seed = rand(1, 1e9)
@@ -73,6 +69,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/list/_subsystems = list()
subsystems = _subsystems
+ // Highlander-style: there can only be one! Kill off the old and replace it with the new.
if(Master != src)
if(istype(Master))
Recover()
@@ -146,7 +143,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
msg = "The [BadBoy.name] subsystem was the last to fire for 2 controller restarts. It will be recovered now and disabled if it happens again."
FireHim = TRUE
if(3)
- msg = "The [BadBoy.name] subsystem seems to be destabilizing the MC and will be offlined."
+ msg = "The [BadBoy.name] subsystem seems to be destabilizing the MC and will be offlined. The following implications are now in effect: [BadBoy.offline_implications]"
BadBoy.flags |= SS_NO_FIRE
if(msg)
to_chat(GLOB.admins, "[msg]")
@@ -454,14 +451,15 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
// in those cases, so we just let them run)
if(queue_node_flags & SS_NO_TICK_CHECK)
if(queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker)
- queue_node.queued_priority += queue_priority_count * 0.1
- queue_priority_count -= queue_node_priority
- queue_priority_count += queue_node.queued_priority
- current_tick_budget -= queue_node_priority
- queue_node = queue_node.queue_next
+ if(!(queue_node_flags & SS_BACKGROUND))
+ queue_node.queued_priority += queue_priority_count * 0.1
+ queue_priority_count -= queue_node_priority
+ queue_priority_count += queue_node.queued_priority
+ current_tick_budget -= queue_node_priority
+ queue_node = queue_node.queue_next
continue
- if((queue_node_flags & SS_BACKGROUND) && !bg_calc)
+ if(!bg_calc && (queue_node_flags & SS_BACKGROUND))
current_tick_budget = queue_priority_count_bg
bg_calc = TRUE
@@ -514,7 +512,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
queue_node.paused_ticks = 0
queue_node.paused_tick_usage = 0
- if(queue_node_flags & SS_BACKGROUND) //update our running total
+ if(bg_calc) //update our running total
queue_priority_count_bg -= queue_node_priority
else
queue_priority_count -= queue_node_priority
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index b8996f2cf89..c9934b128cf 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -1,7 +1,7 @@
/datum/controller/subsystem
// Metadata; you should define these.
- name = "fire coderbus" //name of the subsystem
+ name = "fire codertrain" //name of the subsystem
var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Use defines in __DEFINES/subsystems.dm for easy understanding of order.
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
@@ -35,6 +35,8 @@
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
+ var/offline_implications = "None. No immediate action is needed." // What are the implications of this SS being offlined?
+
//Do not override
///datum/controller/subsystem/New()
@@ -87,7 +89,7 @@
queue_node_flags = queue_node.flags
if(queue_node_flags & SS_TICKER)
- if(!(SS_flags & SS_TICKER))
+ if((SS_flags & (SS_TICKER|SS_BACKGROUND)) != SS_TICKER)
continue
if(queue_node_priority < SS_priority)
break
@@ -179,7 +181,7 @@
var/title = name
if(can_fire)
- title = "\[[state_letter()]][title]"
+ title = "[state_colour()]\[[state_letter()]][title]"
stat(title, statclick.update(msg))
@@ -196,6 +198,18 @@
if(SS_IDLE)
. = " "
+/datum/controller/subsystem/proc/state_colour()
+ switch(state)
+ if(SS_RUNNING) // If its actively processing, colour it green
+ . = ""
+ if(SS_QUEUED) // If its in the running queue, but delayed, colour it orange
+ . = ""
+ if(SS_PAUSED, SS_PAUSING) // If its being paused due to lag, colour it red
+ . = ""
+ if(SS_SLEEPING) // If fire() slept, colour it blue
+ . = ""
+ if(SS_IDLE) // Leave it default if the SS is idle
+ . = ""
//could be used to postpone a costly subsystem for (default one) var/cycles, cycles
//for instance, during cpu intensive operations like explosions
/datum/controller/subsystem/proc/postpone(cycles = 1)
diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm
index 40063b00a87..119d82113d7 100644
--- a/code/controllers/subsystem/acid.dm
+++ b/code/controllers/subsystem/acid.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(acid)
priority = FIRE_PRIORITY_ACID
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Objects will no longer react to acid. No immediate action is needed."
var/list/currentrun = list()
var/list/processing = list()
diff --git a/code/controllers/subsystem/afk.dm b/code/controllers/subsystem/afk.dm
index 6ab1d67a816..25ccda3349c 100644
--- a/code/controllers/subsystem/afk.dm
+++ b/code/controllers/subsystem/afk.dm
@@ -1,63 +1,77 @@
-#define AFK_WARNED 1
-#define AFK_CRYOD 2
+#define AFK_WARNED 1
+#define AFK_CRYOD 2
+#define AFK_ADMINS_WARNED 3
SUBSYSTEM_DEF(afk)
name = "AFK Watcher"
wait = 300
flags = SS_BACKGROUND
+ offline_implications = "Players will no longer be marked as AFK. No immediate action is needed."
var/list/afk_players = list() // Associative list. ckey as key and AFK state as value
+ var/list/non_cryo_antags
/datum/controller/subsystem/afk/Initialize()
- if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0)
- flags |= SS_NO_FIRE
+ if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0)
+ flags |= SS_NO_FIRE
+ else
+ non_cryo_antags = list(SPECIAL_ROLE_ABDUCTOR_AGENT, SPECIAL_ROLE_ABDUCTOR_SCIENTIST, \
+ SPECIAL_ROLE_SHADOWLING, SPECIAL_ROLE_WIZARD, SPECIAL_ROLE_WIZARD_APPRENTICE, SPECIAL_ROLE_NUKEOPS)
+ return ..()
/datum/controller/subsystem/afk/fire()
var/list/toRemove = list()
- for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
- if(!H.ckey) // Useless non ckey creatures
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ if(!H?.ckey) // Useless non ckey creatures
continue
-
- var/turf/T
+
+ var/turf/T
// Only players and players with the AFK watch enabled
- // No dead, unconcious, restrained, people without jobs, people on other Z levels than the station or antags
+ // No dead, unconcious, restrained, people without jobs or people on other Z levels than the station
if(!H.client || !H.client.prefs.afk_watch || !H.mind || \
- H.stat || H.restrained() || !H.job || H.mind.special_role || \
- !is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization
- if(afk_players[H.ckey])
+ H.stat || H.restrained() || !H.job || !is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization
+ if(afk_players[H.ckey])
toRemove += H.ckey
continue
-
+
var/mins_afk = round(H.client.inactivity / 600)
if(mins_afk < config.warn_afk_minimum)
if(afk_players[H.ckey])
toRemove += H.ckey
continue
-
+
if(!afk_players[H.ckey])
afk_players[H.ckey] = AFK_WARNED
warn(H, "You are AFK for [mins_afk] minutes. You will be cryod after [config.auto_cryo_afk] total minutes and fully despawned after [config.auto_despawn_afk] total minutes. Please move or click in game if you want to avoid being despawned.")
- else
+ else
var/area/A = T.loc // Turfs loc is the area
if(afk_players[H.ckey] == AFK_WARNED)
if(mins_afk >= config.auto_cryo_afk && A.can_get_auto_cryod)
if(A.fast_despawn)
toRemove += H.ckey
- warn(H, "You are have been despawned after being AFK for [mins_afk] minutes. You have been despawned instantly due to you being in a secure area.")
- msg_admins(H, mins_afk, T, "forcefully despawned", "AFK in a fast despawn area")
+ warn(H, "You have been despawned after being AFK for [mins_afk] minutes. You have been despawned instantly due to you being in a secure area.")
+ log_afk_action(H, mins_afk, T, "despawned", "AFK in a fast despawn area")
force_cryo_human(H)
- else if(cryo_ssd(H))
- afk_players[H.ckey] = AFK_CRYOD
- msg_admins(H, mins_afk, T, "put into cryostorage")
- warn(H, "You are AFK for [mins_afk] minutes and have been moved to cryostorage. After being AFK for [config.auto_despawn_afk] total minutes you will be fully despawned. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.")
-
- else if(mins_afk >= config.auto_despawn_afk)
- var/obj/machinery/cryopod/P = H.loc
- msg_admins(H, mins_afk, T, "forcefully despawned")
- warn(H, "You are have been despawned after being AFK for [mins_afk] minutes.")
+ else
+ if(!(H.mind.special_role in non_cryo_antags))
+ if(cryo_ssd(H))
+ H.create_log(MISC_LOG, "Put into cryostorage by the AFK subsystem")
+ afk_players[H.ckey] = AFK_CRYOD
+ log_afk_action(H, mins_afk, T, "put into cryostorage")
+ warn(H, "You are AFK for [mins_afk] minutes and have been moved to cryostorage. \
+ After being AFK for another [config.auto_despawn_afk] minutes you will be fully despawned. \
+ Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.")
+ else
+ message_admins("[key_name_admin(H)] at ([get_area(T).name] [ADMIN_JMP(T)]) is AFK for [mins_afk] and can't be automatically cryod due to it's antag status: ([H.mind.special_role]).")
+ afk_players[H.ckey] = AFK_ADMINS_WARNED
+
+ else if(afk_players[H.ckey] != AFK_ADMINS_WARNED && mins_afk >= config.auto_despawn_afk)
+ log_afk_action(H, mins_afk, T, "despawned")
+ warn(H, "You have been despawned after being AFK for [mins_afk] minutes.")
toRemove += H.ckey
- P.despawn_occupant()
-
+ force_cryo_human(H)
+
removeFromWatchList(toRemove)
/datum/controller/subsystem/afk/proc/warn(mob/living/carbon/human/H, text)
@@ -66,9 +80,8 @@ SUBSYSTEM_DEF(afk)
if(H.client)
window_flash(H.client)
-/datum/controller/subsystem/afk/proc/msg_admins(mob/living/carbon/human/H, mins_afk, turf/location, action, info)
+/datum/controller/subsystem/afk/proc/log_afk_action(mob/living/carbon/human/H, mins_afk, turf/location, action, info)
log_admin("[key_name(H)] has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]")
- message_admins("[key_name_admin(H)] at ([get_area(location).name] [ADMIN_JMP(location)]) has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]")
/datum/controller/subsystem/afk/proc/removeFromWatchList(list/toRemove)
for(var/C in toRemove)
@@ -79,3 +92,4 @@ SUBSYSTEM_DEF(afk)
#undef AFK_WARNED
#undef AFK_CRYOD
+#undef AFK_ADMINS_WARNED
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 6f2a451ef76..80ce66d13ec 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(air)
wait = 5
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Turfs will no longer process atmos, and all atmospheric machines (including cryotubes) will no longer function. Shuttle call recommended."
var/cost_turfs = 0
var/cost_groups = 0
var/cost_highpressure = 0
diff --git a/code/controllers/subsystem/alarm.dm b/code/controllers/subsystem/alarm.dm
index bac32a449de..289adf6de40 100644
--- a/code/controllers/subsystem/alarm.dm
+++ b/code/controllers/subsystem/alarm.dm
@@ -1,6 +1,7 @@
SUBSYSTEM_DEF(alarms)
name = "Alarms"
init_order = INIT_ORDER_ALARMS // 2
+ offline_implications = "Alarms (Power, camera, fire, etc) will no longer be checked. No immediate action is needed."
var/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
var/datum/alarm_handler/burglar/burglar_alarm = new()
var/datum/alarm_handler/camera/camera_alarm = new()
diff --git a/code/controllers/subsystem/changelog.dm b/code/controllers/subsystem/changelog.dm
new file mode 100644
index 00000000000..98188599abd
--- /dev/null
+++ b/code/controllers/subsystem/changelog.dm
@@ -0,0 +1,263 @@
+/*
+ Subsystem core for ParadiseSS13 changelogs
+ Author: AffectedArc07
+
+ Basically this SS extracts changelogs from the past 30 days from the database, and cleanly formats them into HTML that the players can see
+ It only runs the extraction on initialize to ensure that the changelog doesnt change mid round, and to reduce the amount of DB calls that need to be done
+ The changelog entries are generated from the PHP scripts in tools/githubChangelogProcessor.php
+
+ This SS also handles the checking of player CL dates and informing them if it has changed
+
+*/
+
+SUBSYSTEM_DEF(changelog)
+ name = "Changelog"
+ flags = SS_NO_FIRE
+ var/current_cl_timestamp = "0" // Timestamp is seconds since UNIX epoch (1st January 1970). ITs also a string because BYOND doesnt like big numbers.
+ var/ss_ready = FALSE // Is the SS ready? We dont want to run procs if we have not generated yet
+ var/list/startup_clients_button = list() // Clients who connected before initialization who need their button color updating
+ var/list/startup_clients_open = list() // Clients who connected before initialization who need the CL opening
+ var/changelogHTML = "" // HTML that the changelog will use to display
+
+/datum/controller/subsystem/changelog/Initialize()
+ // This entire subsystem relies on SQL being here.
+ if(!GLOB.dbcon.IsConnected())
+ return ..()
+
+ var/DBQuery/latest_cl_date = GLOB.dbcon.NewQuery("SELECT UNIX_TIMESTAMP(date_merged) AS ut FROM [format_table_name("changelog")] ORDER BY date_merged DESC LIMIT 1")
+ if(!latest_cl_date.Execute())
+ var/err = latest_cl_date.ErrorMsg()
+ log_game("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n")
+ message_admins("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n")
+ // Abort if we cant do this
+ return ..()
+
+ while(latest_cl_date.NextRow())
+ current_cl_timestamp = latest_cl_date.item[1]
+
+ if(!GenerateChangelogHTML()) // if this failed to generate
+ to_chat(world, "WARNING: Changelog failed to generate. Please inform a coder/server dev")
+ return ..()
+
+ ss_ready = TRUE
+ // Now we can alert anyone who wanted to check the changelog
+ for(var/x in startup_clients_button)
+ var/client/C = x
+ UpdatePlayerChangelogButton(C)
+
+ // Now we can alert anyone who wanted to check the changelog
+ for(var/client/C in startup_clients_open)
+ OpenChangelog(C)
+
+ return ..()
+
+
+/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogDate(client/C)
+ if(!ss_ready)
+ return // Only return here, we dont have to worry about a queue list because this will be called from ShowChangelog()
+ // Technically this is only for the date but we can also do the UI button at the same time
+ var/datum/preferences/P = GLOB.preferences_datums[C.ckey]
+ if(P.toggles & UI_DARKMODE)
+ winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none")
+ else
+ winset(C, "rpane.changelog", "background-color=none;font-style=none")
+ C.prefs.lastchangelog = current_cl_timestamp
+ var/DBQuery/updatePlayerCLTime = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[sanitizeSQL(current_cl_timestamp)]' WHERE ckey='[C.ckey]'")
+ if(!updatePlayerCLTime.Execute())
+ var/err = updatePlayerCLTime.ErrorMsg()
+ log_game("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n")
+ message_admins("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n")
+ to_chat(C, "Couldn't update your last seen changelog, please try again later.")
+ return FALSE
+ return TRUE
+
+/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogButton(client/C)
+ // If SQL aint even enabled, just set the button to default style
+ if(!GLOB.dbcon.IsConnected())
+ if(C.prefs.toggles & UI_DARKMODE)
+ winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
+ else
+ winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
+ return
+
+ // If SQL is enabled but we aint ready, queue them up, and use the default style
+ if(!ss_ready)
+ startup_clients_button |= C
+ if(C.prefs.toggles & UI_DARKMODE)
+ winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
+ else
+ winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
+ return
+
+ // Sanity check to ensure clients still exist (If a client DCs mid startup this would runtime)
+ if(C && C.prefs)
+ // If we are ready, process the button style
+ if(C.prefs.lastchangelog != current_cl_timestamp)
+ winset(C, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold")
+ to_chat(C, "Changelog has changed since your last visit.")
+ else
+ if(C.prefs.toggles & UI_DARKMODE)
+ winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
+ else
+ winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
+
+
+/datum/controller/subsystem/changelog/proc/OpenChangelog(client/C)
+ // If SQL isnt enabled, dont even queue them, just tell them it wont work
+ if(!GLOB.dbcon.IsConnected())
+ to_chat(C, "This server is not running with an SQL backend. Changelog is unavailable.")
+ return
+
+ // If SQL is enabled but we aint ready, queue them up
+ if(!ss_ready)
+ startup_clients_open |= C
+ to_chat(C, "The changelog system is still initializing. The changelog will open for you once it has initialized.")
+ return
+
+ UpdatePlayerChangelogDate(C)
+ UpdatePlayerChangelogButton(C)
+
+ var/datum/browser/cl_popup = new(C.mob, "changelog", "Changelog", 700, 800)
+ cl_popup.set_content(changelogHTML)
+ cl_popup.open()
+
+/client/verb/changes()
+ set name = "Changelog"
+ set desc = "View the changelog."
+ set category = "OOC"
+ // Just invoke the actual CL thing
+ SSchangelog.OpenChangelog(src)
+
+// Helper to turn CL types into a fontawesome icon instead of an image
+// The colors are #28a745 for green, #fd7e14 for orange, and #dc3545 for red.
+// These colours are from bootstrap and look good with black and white
+/datum/controller/subsystem/changelog/proc/Text2Icon(text)
+ switch(text)
+ if("FIX")
+ return "" // Fixes are white because while they are good, they have no negative coutnerpart
+ if("WIP")
+ return "" // WIP stuff is orange because new code is good but its not done yet
+ if("TWEAK")
+ return "" // Tweaks are white because they could be good or bad, and theres no specific add or remove
+ if("SOUNDADD")
+ return "" // Sound additions are green because its something new
+ if("SOUNDDEL")
+ return "" // Sound removals are red because something has been removed
+ if("CODEADD")
+ return "" // Code additions are green because its something new
+ if("CODEDEL")
+ return "" // Code removals are red becuase someting has been removed
+ if("IMAGEADD")
+ return "" // Image additions are green because something has been added
+ if("IMAGEDEL")
+ return "" // Image removals are red because something has been removed
+ if("SPELLCHECK")
+ return "" // Spellcheck is white because theres no dedicated negative to it, so theres no red for it to collate with
+ if("EXPERIMENT")
+ return "" // Experimental stuff is orange because while its a new feature, its unstable
+ else // Just incase the DB somehow breaks
+ return "" // Same here
+
+// This proc is the star of the show
+/datum/controller/subsystem/changelog/proc/GenerateChangelogHTML()
+ // Modify the code below to modify the header of the changelog
+ var/changelog_header = {"
+
+ ParadiseSS13 Changelog
+
+
+ "}
+
+ var/list/prs_to_process = list()
+ // Grab all from last 30 days
+ var/DBQuery/pr_list_query = GLOB.dbcon.NewQuery("SELECT DISTINCT pr_number FROM changelog WHERE date_merged BETWEEN NOW() - INTERVAL 30 DAY AND NOW() ORDER BY date_merged DESC")
+ if(!pr_list_query.Execute())
+ var/err = pr_list_query.ErrorMsg()
+ log_game("SQL ERROR during CL generation L143. Error: \[[err]\]\n")
+ message_admins("SQL ERROR during CL generation L143. Error: \[[err]\]\n")
+ return FALSE
+
+ while(pr_list_query.NextRow())
+ prs_to_process += text2num(pr_list_query.item[1])
+
+ // Load in the header
+ changelogHTML += changelog_header
+
+ // Make blocks for all the PRs
+ for(var/pr_number in prs_to_process)
+ // Initial declarations
+ var/pr_block = "" // HTML for the changelog section
+ var/author = "" // Author of the PR
+ var/merge_date = "" // Timestamp of when the PR was merged
+
+ // Now we gather the data from the DB
+ // Also we probably dont need to sanitize the PR number but you never know
+ var/DBQuery/pr_meta = GLOB.dbcon.NewQuery("SELECT author,DATE(date_merged) AS date FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)] LIMIT 1")
+ if(!pr_meta.Execute())
+ var/err = pr_meta.ErrorMsg()
+ log_game("SQL ERROR during CL generation L190. Error: \[[err]\]\n")
+ message_admins("SQL ERROR during CL generation L190. Error: \[[err]\]\n")
+ return FALSE
+
+ while(pr_meta.NextRow())
+ author = pr_meta.item[1]
+ merge_date = pr_meta.item[2]
+
+ // Now for each actual entry
+ var/DBQuery/db_entries = GLOB.dbcon.NewQuery("SELECT cl_type, cl_entry FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)]")
+ if(!db_entries.Execute())
+ var/err = db_entries.ErrorMsg()
+ log_game("SQL ERROR during CL generation L204. Error: \[[err]\]\n")
+ message_admins("SQL ERROR during CL generation L204. Error: \[[err]\]\n")
+ return FALSE
+
+
+ // Now we make a changelog block
+ pr_block += "
"
+ // If the github URL in the config has a trailing slash, it doesnt matter here, thankfully github accepts having a double slash: https://github.com/org/repo//pull/1
+ pr_block += "
#[pr_number] by [author] (Merged on [merge_date])"
+
+ while(db_entries.NextRow())
+ pr_block += "
"
+
+ changelogHTML += pr_block
+
+ // Make sure we return TRUE so we know it worked
+ return TRUE
+
+
+// Topic handler so that PRs and forums and stuff open in another window
+/datum/controller/subsystem/changelog/Topic(href, href_list)
+ // Handler to open pages in your browser instead of inside the CL window
+ // Yes usr.client is gross here but src is the subsystem
+ // Takes the page to open as an argument
+ if(href_list["openPage"])
+ switch(href_list["openPage"])
+ if("forum")
+ usr.client.forum()
+ if("wiki")
+ // Wiki needs snowflake because it has no cancel button
+ if(config.wikiurl)
+ if(alert("This will open the wiki in your browser. Are you sure?",,"Yes","No")=="No")
+ return
+ usr.client.wiki("") // Blank arg is important here
+ else
+ to_chat(usr, "The Wiki URL is not set in the server configuration. Please inform the server host.")
+
+ if("github")
+ usr.client.github()
+ // Takes a PR number as argument
+ if(href_list["openPR"])
+ if(config.githuburl)
+ if(alert("This will open PR #[href_list["openPR"]] in your browser. Are you sure?",,"Yes","No")=="No")
+ return
+ var/url = "[config.githuburl]/pull/[href_list["openPR"]]"
+ usr << link(url)
+ else
+ to_chat(usr, "The GitHub URL is not set in the server configuration. PRs cannot be opened from changelog view. Please inform the server host.")
+
diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm
index dbe38634e6a..4eb468a0952 100644
--- a/code/controllers/subsystem/chat.dm
+++ b/code/controllers/subsystem/chat.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(chat)
wait = 1
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
+ offline_implications = "Chat messages will no longer be cleanly queued. No immediate action is needed."
var/list/payload = list()
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index 1a7ae8ae81a..390c6bc1a62 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -2,6 +2,7 @@ SUBSYSTEM_DEF(events)
name = "Events"
init_order = INIT_ORDER_EVENTS
runlevels = RUNLEVEL_GAME
+ offline_implications = "Random events will no longer happen. No immediate action is needed."
// Report events at the end of the rouund
var/report_at_round_end = 0
@@ -36,7 +37,7 @@ SUBSYSTEM_DEF(events)
E.process()
for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
- var/list/datum/event_container/EC = event_containers[i]
+ var/datum/event_container/EC = event_containers[i]
EC.process()
/datum/controller/subsystem/events/proc/event_complete(var/datum/event/E)
@@ -65,7 +66,7 @@ SUBSYSTEM_DEF(events)
log_debug("Event '[EM.name]' has completed at [station_time_timestamp()].")
/datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay)
- var/list/datum/event_container/EC = event_containers[severity]
+ var/datum/event_container/EC = event_containers[severity]
EC.next_event_time += delay
/datum/controller/subsystem/events/proc/Interact(var/mob/living/user)
@@ -89,7 +90,7 @@ SUBSYSTEM_DEF(events)
if(E.isRunning)
message += "and is still running."
else
- if(E.endedAt - E.startedAt > MinutesToTicks(5)) // Only mention end time if the entire duration was more than 5 minutes
+ if(E.endedAt - E.startedAt > 5 MINUTES) // Only mention end time if the entire duration was more than 5 minutes
message += "and ended at [station_time_timestamp("hh:mm:ss", E.endedAt)]."
else
message += "and ran to completion."
@@ -211,38 +212,38 @@ SUBSYSTEM_DEF(events)
if(href_list["toggle_report"])
report_at_round_end = !report_at_round_end
- admin_log_and_message_admins("has [report_at_round_end ? "enabled" : "disabled"] the round end event report.")
+ log_and_message_admins("has [report_at_round_end ? "enabled" : "disabled"] the round end event report.")
else if(href_list["dec_timer"])
var/datum/event_container/EC = locate(href_list["event"])
var/decrease = (60 * RaiseToPower(10, text2num(href_list["dec_timer"])))
EC.next_event_time -= decrease
- admin_log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by [decrease/600] minute(s).")
+ log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by [decrease/600] minute(s).")
else if(href_list["inc_timer"])
var/datum/event_container/EC = locate(href_list["event"])
var/increase = (60 * RaiseToPower(10, text2num(href_list["inc_timer"])))
EC.next_event_time += increase
- admin_log_and_message_admins("increased timer for [GLOB.severity_to_string[EC.severity]] events by [increase/600] minute(s).")
+ log_and_message_admins("increased timer for [GLOB.severity_to_string[EC.severity]] events by [increase/600] minute(s).")
else if(href_list["select_event"])
var/datum/event_container/EC = locate(href_list["select_event"])
var/datum/event_meta/EM = EC.SelectEvent()
if(EM)
- admin_log_and_message_admins("has queued the [GLOB.severity_to_string[EC.severity]] event '[EM.name]'.")
+ log_and_message_admins("has queued the [GLOB.severity_to_string[EC.severity]] event '[EM.name]'.")
else if(href_list["pause"])
var/datum/event_container/EC = locate(href_list["pause"])
EC.delayed = !EC.delayed
- admin_log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [GLOB.severity_to_string[EC.severity]] events.")
+ log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [GLOB.severity_to_string[EC.severity]] events.")
else if(href_list["interval"])
var/delay = input("Enter delay modifier. A value less than one means events fire more often, higher than one less often.", "Set Interval Modifier") as num|null
if(delay && delay > 0)
var/datum/event_container/EC = locate(href_list["interval"])
EC.delay_modifier = delay
- admin_log_and_message_admins("has set the interval modifier for [GLOB.severity_to_string[EC.severity]] events to [EC.delay_modifier].")
+ log_and_message_admins("has set the interval modifier for [GLOB.severity_to_string[EC.severity]] events to [EC.delay_modifier].")
else if(href_list["stop"])
if(alert("Stopping an event may have unintended side-effects. Continue?","Stopping Event!","Yes","No") != "Yes")
return
var/datum/event/E = locate(href_list["stop"])
var/datum/event_meta/EM = E.event_meta
- admin_log_and_message_admins("has stopped the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
+ log_and_message_admins("has stopped the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
E.kill()
else if(href_list["view_events"])
selected_event_container = locate(href_list["view_events"])
@@ -264,23 +265,23 @@ SUBSYSTEM_DEF(events)
var/datum/event_meta/EM = locate(href_list["set_weight"])
EM.weight = weight
if(EM != new_event)
- admin_log_and_message_admins("has changed the weight of the [GLOB.severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].")
+ log_and_message_admins("has changed the weight of the [GLOB.severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].")
else if(href_list["toggle_oneshot"])
var/datum/event_meta/EM = locate(href_list["toggle_oneshot"])
EM.one_shot = !EM.one_shot
if(EM != new_event)
- admin_log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
+ log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
else if(href_list["toggle_enabled"])
var/datum/event_meta/EM = locate(href_list["toggle_enabled"])
EM.enabled = !EM.enabled
- admin_log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
+ log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
else if(href_list["remove"])
if(alert("This will remove the event from rotation. Continue?","Removing Event!","Yes","No") != "Yes")
return
var/datum/event_meta/EM = locate(href_list["remove"])
var/datum/event_container/EC = locate(href_list["EC"])
EC.available_events -= EM
- admin_log_and_message_admins("has removed the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
+ log_and_message_admins("has removed the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
else if(href_list["add"])
if(!new_event.name || !new_event.event_type)
return
@@ -288,12 +289,12 @@ SUBSYSTEM_DEF(events)
return
new_event.severity = selected_event_container.severity
selected_event_container.available_events += new_event
- admin_log_and_message_admins("has added \a [GLOB.severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].")
+ log_and_message_admins("has added \a [GLOB.severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].")
new_event = new
else if(href_list["clear"])
var/datum/event_container/EC = locate(href_list["clear"])
if(EC.next_event)
- admin_log_and_message_admins("has dequeued the [GLOB.severity_to_string[EC.severity]] event '[EC.next_event.name]'.")
+ log_and_message_admins("has dequeued the [GLOB.severity_to_string[EC.severity]] event '[EC.next_event.name]'.")
EC.next_event = null
Interact(usr)
diff --git a/code/controllers/subsystem/fires.dm b/code/controllers/subsystem/fires.dm
index aafc5ed48d5..dc419fffeb5 100644
--- a/code/controllers/subsystem/fires.dm
+++ b/code/controllers/subsystem/fires.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(fires)
priority = FIRE_PRIOTITY_BURNING
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Objects will no longer react to fires. No immediate action is needed."
var/list/currentrun = list()
var/list/processing = list()
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 4bc3965e6cf..e50c372584a 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -4,9 +4,10 @@ SUBSYSTEM_DEF(garbage)
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
- init_order = INIT_ORDER_GARBAGE
+ init_order = INIT_ORDER_GARBAGE // Why does this have an init order if it has SS_NO_INIT?
+ offline_implications = "Garbage collection is no longer functional, and objects will not be qdel'd. Immediate server restart recommended."
- var/list/collection_timeout = list(0, 2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
+ var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
//Stat tracking
var/delslasttick = 0 // number of del()'s we've done this tick
diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm
index 531b6af2e78..8d6a7e39852 100644
--- a/code/controllers/subsystem/icon_smooth.dm
+++ b/code/controllers/subsystem/icon_smooth.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(icon_smooth)
wait = 1
priority = FIRE_PRIOTITY_SMOOTHING
flags = SS_TICKER
+ offline_implications = "Objects will no longer smooth together properly. No immediate action is needed."
var/list/smooth_queue = list()
@@ -18,8 +19,18 @@ SUBSYSTEM_DEF(icon_smooth)
can_fire = 0
/datum/controller/subsystem/icon_smooth/Initialize()
- smooth_zlevel(1,TRUE)
- smooth_zlevel(2,TRUE)
+ log_startup_progress("Smoothing atoms...")
+ // Smooth EVERYTHING in the world
+ for(var/turf/T in world)
+ if(T.smooth)
+ smooth_icon(T)
+ for(var/A in T)
+ var/atom/AA = A
+ if(AA.smooth)
+ smooth_icon(AA)
+ CHECK_TICK
+
+ // Incase any new atoms were added to the smoothing queue for whatever reason
var/queue = smooth_queue
smooth_queue = list()
for(var/V in queue)
diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm
index 42df941e10f..d61b90f1239 100644
--- a/code/controllers/subsystem/idlenpcpool.dm
+++ b/code/controllers/subsystem/idlenpcpool.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(idlenpcpool)
priority = FIRE_PRIORITY_IDLE_NPC
wait = 60
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Idle simple animals will no longer process. Shuttle call recommended."
var/list/currentrun = list()
var/static/list/idle_mobs_by_zlevel[][]
@@ -39,4 +40,4 @@ SUBSYSTEM_DEF(idlenpcpool)
if(SA.stat != DEAD)
SA.consider_wakeup()
if(MC_TICK_CHECK)
- return
+ return
diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm
index f379deec72b..ecbf1471993 100644
--- a/code/controllers/subsystem/input.dm
+++ b/code/controllers/subsystem/input.dm
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(input)
flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+ offline_implications = "Player input will no longer be recognised. Immediate server restart recommended."
var/list/macro_sets
var/list/movement_keys
@@ -24,7 +25,7 @@ SUBSYSTEM_DEF(input)
// This is for when macro sets are eventualy datumized
/datum/controller/subsystem/input/proc/setup_default_macro_sets()
var/list/static/default_macro_sets
-
+
if(default_macro_sets)
macro_sets = default_macro_sets
return
@@ -120,3 +121,8 @@ SUBSYSTEM_DEF(input)
for(var/i in 1 to clients.len)
var/client/C = clients[i]
C.keyLoop()
+
+/datum/controller/subsystem/input/Recover()
+ macro_sets = SSinput.macro_sets
+ movement_keys = SSinput.movement_keys
+ alt_movement_keys = SSinput.alt_movement_keys
diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm
index b465c65c441..ef89317d0f5 100644
--- a/code/controllers/subsystem/jobs.dm
+++ b/code/controllers/subsystem/jobs.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(jobs)
init_order = INIT_ORDER_JOBS // 12
wait = 3000 // 5 minutes (Deciseconds)
runlevels = RUNLEVEL_GAME
+ offline_implications = "Job playtime hours will no longer be logged. No immediate action is needed."
//List of all jobs
var/list/occupations = list()
@@ -10,7 +11,7 @@ SUBSYSTEM_DEF(jobs)
var/list/type_occupations = list() //Dict of all jobs, keys are types
var/list/prioritized_jobs = list() // List of jobs set to priority by HoP/Captain
var/list/id_change_records = list() // List of all job transfer records
- var/list/id_change_counter = 1
+ var/id_change_counter = 1
//Players who need jobs
var/list/unassigned = list()
//Debug info
@@ -39,8 +40,6 @@ SUBSYSTEM_DEF(jobs)
var/datum/job/job = new J()
if(!job)
continue
- if(!job.faction in faction)
- continue
occupations += job
name_occupations[job.title] = job
type_occupations[J] = job
@@ -138,7 +137,7 @@ SUBSYSTEM_DEF(jobs)
if(flag && !(flag in player.client.prefs.be_special))
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
continue
- if(player.mind && job.title in player.mind.restricted_roles)
+ if(player.mind && (job.title in player.mind.restricted_roles))
Debug("FOC incompatbile with antagonist role, Player: [player]")
continue
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
@@ -180,7 +179,7 @@ SUBSYSTEM_DEF(jobs)
Debug("GRJ player has disability rendering them ineligible for job, Player: [player]")
continue
- if(player.mind && job.title in player.mind.restricted_roles)
+ if(player.mind && (job.title in player.mind.restricted_roles))
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
continue
@@ -357,7 +356,7 @@ SUBSYSTEM_DEF(jobs)
Debug("DO player has disability rendering them ineligible for job, Player: [player], Job:[job.title]")
continue
- if(player.mind && job.title in player.mind.restricted_roles)
+ if(player.mind && (job.title in player.mind.restricted_roles))
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
continue
@@ -498,13 +497,14 @@ SUBSYSTEM_DEF(jobs)
job.after_spawn(H)
//Gives glasses to the vision impaired
- if(H.disabilities & DISABILITY_FLAG_NEARSIGHTED)
+ if(NEARSIGHTED in H.mutations)
var/equipped = H.equip_to_slot_or_del(new /obj/item/clothing/glasses/regular(H), slot_glasses)
if(equipped != 1)
var/obj/item/clothing/glasses/G = H.glasses
if(istype(G) && !G.prescription)
- G.prescription = 1
+ G.prescription = TRUE
G.name = "prescription [G.name]"
+ H.update_nearsighted_effects()
return H
@@ -622,7 +622,9 @@ SUBSYSTEM_DEF(jobs)
if(tgtcard.assignment && tgtcard.assignment == job.title)
jobs_to_formats[job.title] = "disabled" // the job they already have is pre-selected
else if(!job.would_accept_job_transfer_from_player(M))
- jobs_to_formats[job.title] = "linkDiscourage" // karma jobs they don't have available are discouraged
+ jobs_to_formats[job.title] = "linkDiscourage" // jobs which are karma-locked and not unlocked for this player are discouraged
+ else if((job.title in GLOB.command_positions) && istype(M) && M.client && job.available_in_playtime(M.client))
+ jobs_to_formats[job.title] = "linkDiscourage" // command jobs which are playtime-locked and not unlocked for this player are discouraged
else if(job.total_positions && !job.current_positions && job.title != "Civilian")
jobs_to_formats[job.title] = "linkEncourage" // jobs with nobody doing them at all are encouraged
else if(job.total_positions >= 0 && job.current_positions >= job.total_positions)
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 7441d855f22..6761e9647d9 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -1,15 +1,15 @@
-GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update.
-GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update.
-GLOBAL_LIST_EMPTY(lighting_update_objects) // List of lighting objects queued for update.
-
SUBSYSTEM_DEF(lighting)
name = "Lighting"
wait = 2
init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
+ offline_implications = "Lighting will no longer update. Shuttle call recommended."
+ var/static/list/sources_queue = list() // List of lighting sources queued for update.
+ var/static/list/corners_queue = list() // List of lighting corners queued for update.
+ var/static/list/objects_queue = list() // List of lighting objects queued for update.
/datum/controller/subsystem/lighting/stat_entry()
- ..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]")
+ ..("L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]")
/datum/controller/subsystem/lighting/Initialize(timeofday)
if(!initialized)
@@ -30,9 +30,10 @@ SUBSYSTEM_DEF(lighting)
MC_SPLIT_TICK_INIT(3)
if(!init_tick_checks)
MC_SPLIT_TICK
+ var/list/queue = sources_queue
var/i = 0
- for(i in 1 to GLOB.lighting_update_lights.len)
- var/datum/light_source/L = GLOB.lighting_update_lights[i]
+ for(i in 1 to length(queue))
+ var/datum/light_source/L = queue[i]
L.update_corners()
@@ -43,14 +44,15 @@ SUBSYSTEM_DEF(lighting)
else if(MC_TICK_CHECK)
break
if(i)
- GLOB.lighting_update_lights.Cut(1, i+1)
+ queue.Cut(1, i + 1)
i = 0
if(!init_tick_checks)
MC_SPLIT_TICK
- for (i in 1 to GLOB.lighting_update_corners.len)
- var/datum/lighting_corner/C = GLOB.lighting_update_corners[i]
+ queue = corners_queue
+ for(i in 1 to length(queue))
+ var/datum/lighting_corner/C = queue[i]
C.update_objects()
C.needs_update = FALSE
@@ -59,15 +61,16 @@ SUBSYSTEM_DEF(lighting)
else if(MC_TICK_CHECK)
break
if(i)
- GLOB.lighting_update_corners.Cut(1, i+1)
+ queue.Cut(1, i + 1)
i = 0
if(!init_tick_checks)
MC_SPLIT_TICK
- for (i in 1 to GLOB.lighting_update_objects.len)
- var/atom/movable/lighting_object/O = GLOB.lighting_update_objects[i]
+ queue = objects_queue
+ for(i in 1 to length(queue))
+ var/atom/movable/lighting_object/O = queue[i]
if(QDELETED(O))
continue
@@ -79,7 +82,7 @@ SUBSYSTEM_DEF(lighting)
else if(MC_TICK_CHECK)
break
if(i)
- GLOB.lighting_update_objects.Cut(1, i+1)
+ queue.Cut(1, i + 1)
/datum/controller/subsystem/lighting/Recover()
diff --git a/code/controllers/subsystem/machinery.dm b/code/controllers/subsystem/machinery.dm
index 9a73c1dbabb..cebc6a5f768 100644
--- a/code/controllers/subsystem/machinery.dm
+++ b/code/controllers/subsystem/machinery.dm
@@ -6,6 +6,7 @@ SUBSYSTEM_DEF(machines)
name = "Machines"
init_order = INIT_ORDER_MACHINES
flags = SS_KEEP_TIMING
+ offline_implications = "Machinery will no longer process. Shuttle call recommended."
var/list/processing = list()
var/list/currentrun = list()
@@ -41,7 +42,7 @@ SUBSYSTEM_DEF(machines)
while(currentrun.len)
var/obj/O = currentrun[currentrun.len]
currentrun.len--
- if(O)
+ if(O && !QDELETED(O))
var/datum/powernet/newPN = new() // create a new powernet...
propagate_network(O, newPN)//... and propagate it to the other side of the cable
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 17174b02468..163b2635d0e 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -11,26 +11,144 @@ SUBSYSTEM_DEF(mapping)
createRandomZlevel()
// Seed space ruins
if(!config.disable_space_ruins)
- var/timer = start_watch()
- log_startup_progress("Creating random space levels...")
- seedRuins(list(level_name_to_num(EMPTY_AREA)), rand(0, 3), /area/space, GLOB.space_ruins_templates)
- log_startup_progress("Loaded random space levels in [stop_watch(timer)]s.")
-
// load in extra levels of space ruins
-
+ var/load_zlevels_timer = start_watch()
+ log_startup_progress("Creating random space levels...")
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
for(var/i = 1, i <= num_extra_space, i++)
- var/zlev = GLOB.space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED, traits = list(REACHABLE))
- seedRuins(list(zlev), rand(0, 3), /area/space, GLOB.space_ruins_templates)
+ GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
+ log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
+
+ // Now spawn ruins, random budget between 20 and 30 for all zlevels combined.
+ // While this may seem like a high number, the amount of ruin Z levels can be anywhere between 3 and 7.
+ // Note that this budget is not split evenly accross all zlevels
+ log_startup_progress("Seeding ruins...")
+ var/seed_ruins_timer = start_watch()
+ seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
+ log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
+
+ // Makes a blank space level for the sake of randomness
+ GLOB.space_manager.add_new_zlevel("Empty Area", linkage = CROSSLINKED, traits = list(REACHABLE))
+
// Setup the Z-level linkage
GLOB.space_manager.do_transition_setup()
// Spawn Lavaland ruins and rivers.
+ log_startup_progress("Populating lavaland...")
+ var/lavaland_setup_timer = start_watch()
seedRuins(list(level_name_to_num(MINING)), config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, GLOB.lava_ruins_templates)
spawn_rivers(list(level_name_to_num(MINING)))
+ log_startup_progress("Successfully populated lavaland in [stop_watch(lavaland_setup_timer)]s.")
+
+ // Now we make a list of areas for teleport locs
+ // TOOD: Make these locs into lists on the SS itself, not globs
+ for(var/area/AR in world)
+ if(AR.no_teleportlocs)
+ continue
+ if(GLOB.teleportlocs[AR.name])
+ continue
+ var/turf/picked = safepick(get_area_turfs(AR.type))
+ if(picked && is_station_level(picked.z))
+ GLOB.teleportlocs[AR.name] = AR
+
+ GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs)
+
+ for(var/area/AR in world)
+ if(GLOB.ghostteleportlocs[AR.name])
+ continue
+ var/list/turfs = get_area_turfs(AR.type)
+ if(turfs.len)
+ GLOB.ghostteleportlocs[AR.name] = AR
+
+ GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
return ..()
+
+/datum/controller/subsystem/mapping/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
+ if(!z_levels || !z_levels.len)
+ WARNING("No Z levels provided - Not generating ruins")
+ return
+
+ for(var/zl in z_levels)
+ var/turf/T = locate(1, 1, zl)
+ if(!T)
+ WARNING("Z level [zl] does not exist - Not generating ruins")
+ return
+
+ var/list/ruins = potentialRuins.Copy()
+
+ var/list/forced_ruins = list() //These go first on the z level associated (same random one by default)
+ var/list/ruins_availible = list() //we can try these in the current pass
+ var/forced_z //If set we won't pick z level and use this one instead.
+
+ //Set up the starting ruin list
+ for(var/key in ruins)
+ var/datum/map_template/ruin/R = ruins[key]
+ if(R.cost > budget) //Why would you do that
+ continue
+ if(R.always_place)
+ forced_ruins[R] = -1
+ if(R.unpickable)
+ continue
+ ruins_availible[R] = R.placement_weight
+
+ while(budget > 0 && (ruins_availible.len || forced_ruins.len))
+ var/datum/map_template/ruin/current_pick
+ var/forced = FALSE
+ if(forced_ruins.len) //We have something we need to load right now, so just pick it
+ for(var/ruin in forced_ruins)
+ current_pick = ruin
+ if(forced_ruins[ruin] > 0) //Load into designated z
+ forced_z = forced_ruins[ruin]
+ forced = TRUE
+ break
+ else //Otherwise just pick random one
+ current_pick = pickweight(ruins_availible)
+
+ var/placement_tries = PLACEMENT_TRIES
+ var/failed_to_place = TRUE
+ var/z_placed = 0
+ while(placement_tries > 0)
+ placement_tries--
+ z_placed = pick(z_levels)
+ if(!current_pick.try_to_place(forced_z ? forced_z : z_placed,whitelist))
+ continue
+ else
+ failed_to_place = FALSE
+ break
+
+ //That's done remove from priority even if it failed
+ if(forced)
+ //TODO : handle forced ruins with multiple variants
+ forced_ruins -= current_pick
+ forced = FALSE
+
+ if(failed_to_place)
+ for(var/datum/map_template/ruin/R in ruins_availible)
+ if(R.id == current_pick.id)
+ ruins_availible -= R
+ log_world("Failed to place [current_pick.name] ruin.")
+ else
+ budget -= current_pick.cost
+ if(!current_pick.allow_duplicates)
+ for(var/datum/map_template/ruin/R in ruins_availible)
+ if(R.id == current_pick.id)
+ ruins_availible -= R
+ if(current_pick.never_spawn_with)
+ for(var/blacklisted_type in current_pick.never_spawn_with)
+ for(var/possible_exclusion in ruins_availible)
+ if(istype(possible_exclusion,blacklisted_type))
+ ruins_availible -= possible_exclusion
+ forced_z = 0
+
+ //Update the availible list
+ for(var/datum/map_template/ruin/R in ruins_availible)
+ if(R.cost > budget)
+ ruins_availible -= R
+
+ log_world("Ruin loader finished with [budget] left to spend.")
+
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT
diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm
index c21b8f0760a..9445dd2717a 100644
--- a/code/controllers/subsystem/mobs.dm
+++ b/code/controllers/subsystem/mobs.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(mobs)
priority = FIRE_PRIORITY_MOBS
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Mobs will no longer process. Immediate server restart recommended."
var/list/currentrun = list()
var/static/list/clients_by_zlevel[][]
@@ -10,7 +11,7 @@ SUBSYSTEM_DEF(mobs)
var/static/list/cubemonkeys = list()
/datum/controller/subsystem/mobs/stat_entry()
- ..("P:[GLOB.mob_list.len]")
+ ..("P:[GLOB.mob_living_list.len]")
/datum/controller/subsystem/mobs/Initialize(start_timeofday)
clients_by_zlevel = new /list(world.maxz,0)
@@ -20,17 +21,17 @@ SUBSYSTEM_DEF(mobs)
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
if(!resumed)
- src.currentrun = GLOB.mob_list.Copy()
+ src.currentrun = GLOB.mob_living_list.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
var/times_fired = src.times_fired
while(currentrun.len)
- var/mob/M = currentrun[currentrun.len]
+ var/mob/living/L = currentrun[currentrun.len]
currentrun.len--
- if(M)
- M.Life(seconds, times_fired)
+ if(L)
+ L.Life(seconds, times_fired)
else
- GLOB.mob_list.Remove(M)
+ GLOB.mob_living_list.Remove(L)
if(MC_TICK_CHECK)
return
diff --git a/code/controllers/subsystem/nano_mob_hunter.dm b/code/controllers/subsystem/nano_mob_hunter.dm
index a634f091013..b8a5d09e0b5 100644
--- a/code/controllers/subsystem/nano_mob_hunter.dm
+++ b/code/controllers/subsystem/nano_mob_hunter.dm
@@ -2,6 +2,8 @@ SUBSYSTEM_DEF(mob_hunt)
name = "Nano-Mob Hunter GO Server"
init_order = INIT_ORDER_NANOMOB
priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact.
+ flags = SS_NO_INIT
+ offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed."
var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this
var/list/normal_spawns = list()
var/max_trap_spawns = 15 //change this to adjust the number of trap spawns that can exist at one time. traps spawned beyond this point clear the oldest traps
@@ -102,12 +104,12 @@ SUBSYSTEM_DEF(mob_hunt)
return
if(red_terminal && red_terminal.ready && blue_terminal && blue_terminal.ready)
battle_turn = pick("Red", "Blue")
- red_terminal.audible_message("Battle starting!", null, 5)
- blue_terminal.audible_message("Battle starting!", null, 5)
+ red_terminal.atom_say("Battle starting!")
+ blue_terminal.atom_say("Battle starting!")
if(battle_turn == "Red")
- red_terminal.audible_message("Red Player's Turn!", null, 5)
+ red_terminal.atom_say("Red Player's Turn!")
else if(battle_turn == "Blue")
- blue_terminal.audible_message("Blue Player's Turn!", null, 5)
+ blue_terminal.atom_say("Blue Player's Turn!")
/datum/controller/subsystem/mob_hunt/proc/launch_attack(team, raw_damage, datum/mob_type/attack_type)
if(!team || !raw_damage)
@@ -134,11 +136,11 @@ SUBSYSTEM_DEF(mob_hunt)
winner_terminal.ready = 0
loser_terminal.ready = 0
if(surrender) //surrender doesn't give exp, to avoid people just farming exp without actually doing a battle
- winner_terminal.audible_message("Your rival surrendered!", null, 2)
+ winner_terminal.atom_say("Your rival surrendered!")
else
var/progress_message = winner_terminal.mob_info.gain_exp()
- winner_terminal.audible_message("[winner_terminal.team] Player wins!", null, 5)
- winner_terminal.audible_message(progress_message, null, 2)
+ winner_terminal.atom_say("[winner_terminal.team] Player wins!")
+ winner_terminal.atom_say(progress_message)
/datum/controller/subsystem/mob_hunt/proc/end_turn()
red_terminal.updateUsrDialog()
@@ -147,7 +149,7 @@ SUBSYSTEM_DEF(mob_hunt)
return
if(battle_turn == "Red")
battle_turn = "Blue"
- blue_terminal.audible_message("Blue's turn.", null, 5)
+ blue_terminal.atom_say("Blue's turn.")
else if(battle_turn == "Blue")
battle_turn = "Red"
- blue_terminal.audible_message("Red's turn.", null, 5)
+ blue_terminal.atom_say("Red's turn.")
diff --git a/code/controllers/subsystem/nanoui.dm b/code/controllers/subsystem/nanoui.dm
index c8cbbc62013..ef1b6ee03fe 100644
--- a/code/controllers/subsystem/nanoui.dm
+++ b/code/controllers/subsystem/nanoui.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(nanoui)
flags = SS_NO_INIT
priority = FIRE_PRIORITY_NANOUI
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ offline_implications = "All NanoUIs will no longer process. Shuttle call recommended."
var/list/currentrun = list()
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm
index e13f49fd1c2..deffcb6bddf 100644
--- a/code/controllers/subsystem/nightshift.dm
+++ b/code/controllers/subsystem/nightshift.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(nightshift)
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 600
flags = SS_NO_TICK_CHECK
+ offline_implications = "The game will no longer shift between day and night lighting. No immediate action is needed."
var/nightshift_active = FALSE
var/nightshift_start_time = 702000 //7:30 PM, station time
diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm
index 5eaca5d19c4..79541c199a4 100644
--- a/code/controllers/subsystem/npcpool.dm
+++ b/code/controllers/subsystem/npcpool.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(npcpool)
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = FIRE_PRIORITY_NPC
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Simple animals will no longer process. Shuttle call recommended."
var/list/currentrun = list()
diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm
index c35f1adee65..95b9e925b5d 100644
--- a/code/controllers/subsystem/overlays.dm
+++ b/code/controllers/subsystem/overlays.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(overlays)
wait = 1
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
+ offline_implications = "Overlays may look strange. No immediate action is needed."
var/list/queue
var/list/stats
diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm
index 039b6d2b008..9135f62b03f 100644
--- a/code/controllers/subsystem/parallax.dm
+++ b/code/controllers/subsystem/parallax.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(parallax)
flags = SS_POST_FIRE_TIMING | SS_BACKGROUND
priority = FIRE_PRIORITY_PARALLAX
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ offline_implications = "Space parallax will no longer move around. No immediate action is needed."
var/list/currentrun
var/planet_x_offset = 128
var/planet_y_offset = 128
diff --git a/code/controllers/subsystem/processing/dcs.dm b/code/controllers/subsystem/processing/dcs.dm
new file mode 100644
index 00000000000..a223f4676f6
--- /dev/null
+++ b/code/controllers/subsystem/processing/dcs.dm
@@ -0,0 +1,55 @@
+PROCESSING_SUBSYSTEM_DEF(dcs)
+ name = "Datum Component System"
+ flags = SS_NO_INIT
+
+ var/list/elements_by_type = list()
+ // Update this if you add in components which actually use this as a processor
+ offline_implications = "This SS doesnt actually process anything yet. No immediate action is needed."
+
+/datum/controller/subsystem/processing/dcs/Recover()
+ comp_lookup = SSdcs.comp_lookup
+
+/datum/controller/subsystem/processing/dcs/proc/GetElement(list/arguments)
+ var/datum/element/eletype = arguments[1]
+ var/element_id = eletype
+
+ if(!ispath(eletype, /datum/element))
+ CRASH("Attempted to instantiate [eletype] as a /datum/element")
+
+ if(initial(eletype.element_flags) & ELEMENT_BESPOKE)
+ element_id = GetIdFromArguments(arguments)
+
+ . = elements_by_type[element_id]
+ if(.)
+ return
+ . = elements_by_type[element_id] = new eletype
+
+/****
+ * Generates an id for bespoke elements when given the argument list
+ * Generating the id here is a bit complex because we need to support named arguments
+ * Named arguments can appear in any order and we need them to appear after ordered arguments
+ * We assume that no one will pass in a named argument with a value of null
+ **/
+/datum/controller/subsystem/processing/dcs/proc/GetIdFromArguments(list/arguments)
+ var/datum/element/eletype = arguments[1]
+ var/list/fullid = list("[eletype]")
+ var/list/named_arguments = list()
+ for(var/i in initial(eletype.id_arg_index) to length(arguments))
+ var/key = arguments[i]
+ var/value
+ if(istext(key))
+ value = arguments[key]
+ if(!(istext(key) || isnum(key)))
+ key = "\ref[key]"
+ key = "[key]" // Key is stringified so numbers dont break things
+ if(!isnull(value))
+ if(!(istext(value) || isnum(value)))
+ value = "\ref[value]"
+ named_arguments["[key]"] = value
+ else
+ fullid += "[key]"
+
+ if(length(named_arguments))
+ named_arguments = sortList(named_arguments)
+ fullid += named_arguments
+ return list2params(fullid)
diff --git a/code/controllers/subsystem/processing/fastprocess.dm b/code/controllers/subsystem/processing/fastprocess.dm
index 9622e021469..37761ca8d60 100644
--- a/code/controllers/subsystem/processing/fastprocess.dm
+++ b/code/controllers/subsystem/processing/fastprocess.dm
@@ -4,3 +4,4 @@ PROCESSING_SUBSYSTEM_DEF(fastprocess)
name = "Fast Processing"
wait = 2
stat_tag = "FP"
+ offline_implications = "Objects using the 'Fast Processing' processor will no longer process. Shuttle call recommended."
diff --git a/code/controllers/subsystem/processing/obj.dm b/code/controllers/subsystem/processing/obj.dm
index 26021fb267a..2a05c04af58 100644
--- a/code/controllers/subsystem/processing/obj.dm
+++ b/code/controllers/subsystem/processing/obj.dm
@@ -3,3 +3,4 @@ PROCESSING_SUBSYSTEM_DEF(obj)
priority = FIRE_PRIORITY_OBJ
flags = SS_NO_INIT
wait = 20
+ offline_implications = "Objects using the 'Objects' processor will no longer process. Shuttle call recommended."
diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm
index a8bc823bbbe..5302314589d 100644
--- a/code/controllers/subsystem/processing/processing.dm
+++ b/code/controllers/subsystem/processing/processing.dm
@@ -9,6 +9,7 @@ SUBSYSTEM_DEF(processing)
var/stat_tag = "P" //Used for logging
var/list/processing = list()
var/list/currentrun = list()
+ offline_implications = "Objects using the default processor will no longer process. Shuttle call recommended."
/datum/controller/subsystem/processing/stat_entry()
..("[stat_tag]:[processing.len]")
diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm
index 49b30062786..5a49070bf89 100644
--- a/code/controllers/subsystem/radio.dm
+++ b/code/controllers/subsystem/radio.dm
@@ -54,7 +54,7 @@ SUBSYSTEM_DEF(radio)
// If the above switch somehow failed. And it needs the SSradio. part otherwise it fails to compile
if(frequency in DEPT_FREQS)
return "deptradio"
-
+
// If its none of the others
return "radio"
diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm
index da3d91c1de1..247d71d05b8 100644
--- a/code/controllers/subsystem/shuttles.dm
+++ b/code/controllers/subsystem/shuttles.dm
@@ -6,6 +6,7 @@ SUBSYSTEM_DEF(shuttle)
init_order = INIT_ORDER_SHUTTLE
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
+ offline_implications = "Shuttles will no longer function and cargo will not generate points. Immediate server restart recommended."
var/list/mobile = list()
var/list/stationary = list()
var/list/transit = list()
@@ -223,11 +224,12 @@ SUBSYSTEM_DEF(shuttle)
return 0 //dock successful
-/datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed)
+/datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed, mob/user)
var/obj/docking_port/mobile/M = getShuttle(shuttleId)
var/obj/docking_port/stationary/D = getDock(dockId)
if(!M)
return 1
+ M.last_caller = user // Save the caller of the shuttle for later logging
if(timed)
if(M.request(D))
return 2
diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm
index fcc62a2fa50..d9c46f9c9d7 100644
--- a/code/controllers/subsystem/spacedrift.dm
+++ b/code/controllers/subsystem/spacedrift.dm
@@ -4,6 +4,7 @@ SUBSYSTEM_DEF(spacedrift)
wait = 5
flags = SS_NO_INIT|SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Mobs will no longer respect a lack of gravity. No immediate action is needed."
var/list/currentrun = list()
var/list/processing = list()
diff --git a/code/controllers/subsystem/statistics.dm b/code/controllers/subsystem/statistics.dm
new file mode 100644
index 00000000000..3a0bf7e51e2
--- /dev/null
+++ b/code/controllers/subsystem/statistics.dm
@@ -0,0 +1,28 @@
+SUBSYSTEM_DEF(statistics)
+ name = "Statistics"
+ wait = 6000 // 10 minute delay between fires
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME // Only count time actually ingame to avoid logging pre-round dips
+ offline_implications = "Player count and admin count statistics will no longer be logged to the database. No immediate action is needed."
+
+
+/datum/controller/subsystem/statistics/Initialize(start_timeofday)
+ if(!config.sql_enabled)
+ flags |= SS_NO_FIRE // Disable firing if SQL is disabled
+ return ..()
+
+/datum/controller/subsystem/statistics/fire(resumed = 0)
+ sql_poll_players()
+
+/datum/controller/subsystem/statistics/proc/sql_poll_players()
+ if(!config.sql_enabled)
+ return
+ var/playercount = GLOB.clients.len
+ var/admincount = GLOB.admins.len
+ if(!GLOB.dbcon.IsConnected())
+ log_game("SQL ERROR during player polling. Failed to connect.")
+ else
+ var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
+ var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time) VALUES ([playercount], [admincount], '[sqltime]')")
+ if(!query.Execute())
+ var/err = query.ErrorMsg()
+ log_game("SQL ERROR during playercount polling. Error: \[[err]\]\n")
diff --git a/code/controllers/subsystem/sun.dm b/code/controllers/subsystem/sun.dm
index 6cfb52f2d25..3f8e15df05a 100644
--- a/code/controllers/subsystem/sun.dm
+++ b/code/controllers/subsystem/sun.dm
@@ -1,19 +1,29 @@
SUBSYSTEM_DEF(sun)
name = "Sun"
wait = 600
- flags = SS_NO_TICK_CHECK|SS_NO_INIT
+ flags = SS_NO_TICK_CHECK
+ init_order = INIT_ORDER_SUN
+ offline_implications = "Solar panels will no longer rotate. No immediate action is needed."
var/angle
var/dx
var/dy
var/rate
var/list/solars = list()
-/datum/controller/subsystem/sun/PreInit()
+/datum/controller/subsystem/sun/Initialize(start_timeofday)
+ // Lets work out an angle for the "sun" to rotate around the station
angle = rand (0,360) // the station position to the sun is randomised at round start
rate = rand(50,200)/100 // 50% - 200% of standard rotation
if(prob(50)) // same chance to rotate clockwise than counter-clockwise
rate = -rate
+ // Solar consoles need to load after machines init, so this handles that
+ for(var/obj/machinery/power/solar_control/SC in solars)
+ SC.setup()
+
+ return ..()
+
+
/datum/controller/subsystem/sun/stat_entry(msg)
..("P:[solars.len]")
diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm
new file mode 100644
index 00000000000..c4240021137
--- /dev/null
+++ b/code/controllers/subsystem/tgui.dm
@@ -0,0 +1,286 @@
+ /**
+ * tgui subsystem
+ *
+ * Contains all tgui state and subsystem code.
+ **/
+
+
+SUBSYSTEM_DEF(tgui)
+ name = "TGUI"
+ wait = 9
+ flags = SS_NO_INIT
+ priority = FIRE_PRIORITY_NANOUI // Yes I am aware that this is TGUI and I used the nanoUI fire priority. Dont @ me.
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ offline_implications = "All TGUIs will no longer process. Shuttle call recommended."
+
+ var/list/currentrun = list()
+ var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
+ var/list/processing_uis = list() // A list of processing UIs, ungrouped.
+ var/basehtml // The HTML base used for all UIs.
+
+/datum/controller/subsystem/tgui/PreInit()
+ basehtml = file2text('tgui/packages/tgui/public/tgui.html')
+
+/datum/controller/subsystem/tgui/Shutdown()
+ close_all_uis()
+
+/datum/controller/subsystem/tgui/stat_entry()
+ ..("P:[processing_uis.len]")
+
+/datum/controller/subsystem/tgui/fire(resumed = 0)
+ if (!resumed)
+ src.currentrun = processing_uis.Copy()
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+
+ while(currentrun.len)
+ var/datum/tgui/ui = currentrun[currentrun.len]
+ currentrun.len--
+ if(ui && ui.user && ui.src_object)
+ ui.process()
+ else
+ processing_uis.Remove(ui)
+ if (MC_TICK_CHECK)
+ return
+
+ /**
+ * public
+ *
+ * Get a open UI given a user, src_object, and ui_key and try to update it with data.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * required src_object datum The object/datum which owns the UI.
+ * required ui_key string The ui_key of the UI.
+ * optional ui datum/tgui The UI to be updated, if it exists.
+ * optional force_open bool If the UI should be re-opened instead of updated.
+ *
+ * return datum/tgui The found UI.
+ **/
+/datum/controller/subsystem/tgui/proc/try_update_ui(mob/user, datum/src_object, ui_key, datum/tgui/ui, force_open = FALSE)
+ if(isnull(ui)) // No UI was passed, so look for one.
+ ui = get_open_ui(user, src_object, ui_key)
+
+ if(!isnull(ui))
+ var/data = src_object.tgui_data(user) // Get data from the src_object.
+ if(!force_open) // UI is already open; update it.
+ ui.push_data(data)
+ else // Re-open it anyways.
+ ui.reinitialize(null, data)
+ return ui // We found the UI, return it.
+ else
+ return null // We couldn't find a UI.
+
+ /**
+ * private
+ *
+ * Get a open UI given a user, src_object, and ui_key.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * required src_object datum The object/datum which owns the UI.
+ * required ui_key string The ui_key of the UI.
+ *
+ * return datum/tgui The found UI.
+ **/
+/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object, ui_key)
+ var/src_object_key = "[src_object.UID()]"
+ if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
+ return null // No UIs open.
+ else if(isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
+ return null // No UIs open for this object.
+
+ for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) // Find UIs for this object.
+ if(ui.user == user) // Make sure we have the right user
+ return ui
+
+ return null // Couldn't find a UI!
+
+ /**
+ * private
+ *
+ * Update all UIs attached to src_object.
+ *
+ * required src_object datum The object/datum which owns the UIs.
+ *
+ * return int The number of UIs updated.
+ **/
+/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
+ var/src_object_key = "[src_object.UID()]"
+ if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
+ return 0 // Couldn't find any UIs for this object.
+
+ var/update_count = 0
+ for(var/ui_key in open_uis[src_object_key])
+ for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
+ if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid.
+ ui.process(force = 1) // Update the UI.
+ update_count++ // Count each UI we update.
+ return update_count
+
+ /**
+ * private
+ *
+ * Close all UIs attached to src_object.
+ *
+ * required src_object datum The object/datum which owns the UIs.
+ *
+ * return int The number of UIs closed.
+ **/
+/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
+ var/src_object_key = "[src_object.UID()]"
+ if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
+ return 0 // Couldn't find any UIs for this object.
+
+ var/close_count = 0
+ for(var/ui_key in open_uis[src_object_key])
+ for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
+ if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid.
+ ui.close() // Close the UI.
+ close_count++ // Count each UI we close.
+ return close_count
+
+ /**
+ * private
+ *
+ * Close *ALL* UIs
+ *
+ * return int The number of UIs closed.
+ **/
+/datum/controller/subsystem/tgui/proc/close_all_uis()
+ var/close_count = 0
+ for(var/src_object_key in open_uis)
+ for(var/ui_key in open_uis[src_object_key])
+ for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
+ if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid.
+ ui.close() // Close the UI.
+ close_count++ // Count each UI we close.
+ return close_count
+
+ /**
+ * private
+ *
+ * Update all UIs belonging to a user.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * optional src_object datum If provided, only update UIs belonging this src_object.
+ * optional ui_key string If provided, only update UIs with this UI key.
+ *
+ * return int The number of UIs updated.
+ **/
+/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object = null, ui_key = null)
+ if(isnull(user.open_tguis) || !istype(user.open_tguis, /list) || open_uis.len == 0)
+ return 0 // Couldn't find any UIs for this user.
+
+ var/update_count = 0
+ for(var/datum/tgui/ui in user.open_tguis)
+ 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(force = 1) // Update the UI.
+ update_count++ // Count each UI we upadte.
+ return update_count
+
+ /**
+ * private
+ *
+ * Close all UIs belonging to a user.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * optional src_object datum If provided, only close UIs belonging this src_object.
+ * optional ui_key string If provided, only close UIs with this UI key.
+ *
+ * return int The number of UIs closed.
+ **/
+/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object = null, ui_key = null)
+ if(isnull(user.open_tguis) || !istype(user.open_tguis, /list) || open_uis.len == 0)
+ return 0 // Couldn't find any UIs for this user.
+
+ var/close_count = 0
+ for(var/datum/tgui/ui in user.open_tguis)
+ if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
+ ui.close() // Close the UI.
+ close_count++ // Count each UI we close.
+ return close_count
+
+ /**
+ * private
+ *
+ * Add a UI to the list of open UIs.
+ *
+ * required ui datum/tgui The UI to be added.
+ **/
+/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
+ var/src_object_key = "[ui.src_object.UID()]"
+ if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
+ open_uis[src_object_key] = list(ui.ui_key = list()) // Make a list for the ui_key and src_object.
+ else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
+ open_uis[src_object_key][ui.ui_key] = list() // Make a list for the ui_key.
+
+ // Append the UI to all the lists.
+ ui.user.open_tguis |= ui
+ var/list/uis = open_uis[src_object_key][ui.ui_key]
+ uis |= ui
+ processing_uis |= ui
+
+ /**
+ * private
+ *
+ * Remove a UI from the list of open UIs.
+ *
+ * required ui datum/tgui The UI to be removed.
+ *
+ * return bool If the UI was removed or not.
+ **/
+/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
+ var/src_object_key = "[ui.src_object.UID()]"
+ if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
+ return FALSE // It wasn't open.
+ else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
+ return FALSE // It wasn't open.
+
+ processing_uis.Remove(ui) // Remove it from the list of processing UIs.
+ if(ui.user) // If the user exists, remove it from them too.
+ ui.user.open_tguis.Remove(ui)
+ var/Ukey = ui.ui_key
+ var/list/uis = open_uis[src_object_key][Ukey] // Remove it from the list of open UIs.
+ uis.Remove(ui)
+ if(!uis.len)
+ var/list/uiobj = open_uis[src_object_key]
+ uiobj.Remove(Ukey)
+ if(!uiobj.len)
+ open_uis.Remove(src_object_key)
+
+ return TRUE // Let the caller know we did it.
+
+ /**
+ * private
+ *
+ * Handle client logout, by closing all their UIs.
+ *
+ * required user mob The mob which logged out.
+ *
+ * return int The number of UIs closed.
+ **/
+/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
+ return close_user_uis(user)
+
+ /**
+ * private
+ *
+ * Handle clients switching mobs, by transferring their UIs.
+ *
+ * required user source The client's original mob.
+ * required user target The client's new mob.
+ *
+ * return bool If the UIs were transferred.
+ **/
+/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
+ if(!source || isnull(source.open_tguis) || !istype(source.open_tguis, /list) || open_uis.len == 0)
+ return FALSE // The old mob had no open UIs.
+
+ if(isnull(target.open_tguis) || !istype(target.open_tguis, /list))
+ target.open_tguis = list() // Create a list for the new mob if needed.
+
+ for(var/datum/tgui/ui in source.open_tguis)
+ ui.user = target // Inform the UIs of their new owner.
+ target.open_tguis.Add(ui) // Transfer all the UIs.
+
+ source.open_tguis.Cut() // Clear the old list.
+ return TRUE // Let the caller know we did it.
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 74dbf4c4d93..04ddf40f442 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -7,6 +7,7 @@ SUBSYSTEM_DEF(throwing)
wait = 1
flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ offline_implications = "Thrown objects may not react properly. Shuttle call recommended."
var/list/currentrun
var/list/processing = list()
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index bbc73cfed14..5d0a53c221e 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(ticker)
priority = FIRE_PRIORITY_TICKER
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME
+ offline_implications = "The game is no longer aware of when the round ends. Immediate server restart recommended."
var/round_start_time = 0
var/const/restart_timeout = 600
@@ -23,15 +24,12 @@ SUBSYSTEM_DEF(ticker)
var/Bible_deity_name
var/datum/cult_info/cultdat = null //here instead of cult for adminbus purposes
var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
- var/list/syndicate_coalition = list() // list of traitor-compatible factions
- var/list/factions = list() // list of all factions
- var/list/availablefactions = list() // list of factions with openings
var/tipped = FALSE //Did we broadcast the tip of the day yet?
var/selected_tip // What will be the tip of the day?
var/pregame_timeleft // This is used for calculations
var/delay_end = 0 //if set to nonzero, the round will not restart on it's own
var/triai = 0//Global holder for Triumvirate
- var/initialtpass = 0 //holder for inital autotransfer vote timer
+ var/next_autotransfer = 0 //holder for inital autotransfer vote timer
var/obj/screen/cinematic = null //used for station explosion cinematic
var/round_end_announced = 0 // Spam Prevention. Announce round end only once.
var/ticker_going = TRUE // This used to be in the unused globals, but it turns out its actually used in a load of places. Its now a ticker var because its related to round stuff, -aa
@@ -92,12 +90,17 @@ SUBSYSTEM_DEF(ticker)
delay_end = 0 // reset this in case round start was delayed
mode.process()
mode.process_job_tasks()
+
+ if(world.time > next_autotransfer)
+ SSvote.autotransfer()
+ next_autotransfer = world.time + config.vote_autotransfer_interval
+
var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked
if(config.continuous_rounds)
mode.check_finished() // some modes contain var-changing code in here, so call even if we don't uses result
else
game_finished |= mode.check_finished()
- if(game_finished)
+ if(game_finished || force_ending)
current_state = GAME_STATE_FINISHED
if(GAME_STATE_FINISHED)
current_state = GAME_STATE_FINISHED
@@ -113,19 +116,6 @@ SUBSYSTEM_DEF(ticker)
else
world.Reboot("Round ended.", "end_proper", "proper completion")
-
-/datum/controller/subsystem/ticker/proc/votetimer()
- var/timerbuffer = 0
- if(initialtpass == 0)
- timerbuffer = config.vote_autotransfer_initial
- else
- timerbuffer = config.vote_autotransfer_interval
- spawn(timerbuffer)
- SSvote.autotransfer()
- initialtpass = 1
- votetimer()
-
-
/datum/controller/subsystem/ticker/proc/setup()
cultdat = setupcult()
//Create and announce mode
@@ -190,11 +180,17 @@ SUBSYSTEM_DEF(ticker)
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
- callHook("roundstart")
+ // Generate the list of playable AI cores in the world
+ for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
+ if(S.name != "AI")
+ continue
+ if(locate(/mob/living) in S.loc)
+ continue
+ GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S))
+
//here to initialize the random events nicely at round start
setup_economy()
- setupfactions()
//shuttle_controller.setup_shuttle_docks()
@@ -284,17 +280,28 @@ SUBSYSTEM_DEF(ticker)
auto_toggle_ooc(0) // Turn it off
round_start_time = world.time
- if(config.sql_enabled)
- spawn(3000)
- statistic_cycle() // Polls population totals regularly and stores them in an SQL DB
-
- votetimer()
+ // Sets the auto shuttle vote to happen after the config duration
+ next_autotransfer = world.time + config.vote_autotransfer_initial
for(var/mob/new_player/N in GLOB.mob_list)
if(N.client)
N.new_player_panel_proc()
- return 1
+ // Now that every other piece of the round has initialized, lets setup player job scaling
+ var/playercount = length(GLOB.clients)
+ var/highpop_trigger = 80
+
+ if(playercount >= highpop_trigger)
+ log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config")
+ SSjobs.LoadJobs("config/jobs_highpop.txt")
+ else
+ log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config")
+
+ #ifdef UNIT_TESTS
+ RunUnitTests()
+ #endif
+ return TRUE
+
/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(station_missed = 0, override = null)
if(cinematic)
@@ -309,15 +316,12 @@ SUBSYSTEM_DEF(ticker)
cinematic.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
cinematic.screen_loc = "1,0"
- var/obj/structure/bed/temp_buckle = new(src)
if(station_missed)
for(var/mob/M in GLOB.mob_list)
- M.buckled = temp_buckle //buckles the mob so it can't do anything
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
for(var/mob/M in GLOB.mob_list)
- M.buckled = temp_buckle
if(M.stat != DEAD)
var/turf/T = get_turf(M)
if(T && is_station_level(T.z) && !istype(M.loc, /obj/structure/closet/secure_closet/freezer))
@@ -387,8 +391,6 @@ SUBSYSTEM_DEF(ticker)
//Otherwise if its a verb it will continue on afterwards.
spawn(300)
QDEL_NULL(cinematic) //end the cinematic
- if(temp_buckle)
- qdel(temp_buckle) //release everybody
@@ -424,7 +426,7 @@ SUBSYSTEM_DEF(ticker)
EquipCustomItems(player)
if(captainless)
for(var/mob/M in GLOB.player_list)
- if(!istype(M,/mob/new_player))
+ if(!isnewplayer(M))
to_chat(M, "Captainship not forced on anyone.")
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
@@ -442,12 +444,6 @@ SUBSYSTEM_DEF(ticker)
if(m)
to_chat(world, "Tip of the round: [html_encode(m)]")
-/datum/controller/subsystem/ticker/proc/getfactionbyname(var/name)
- for(var/datum/faction/F in factions)
- if(F.name == name)
- return F
-
-
/datum/controller/subsystem/ticker/proc/declare_completion()
GLOB.nologevent = 1 //end of round murder and shenanigans are legal; there's no need to jam up attack logs past this point.
//Round statistics report
@@ -518,6 +514,11 @@ SUBSYSTEM_DEF(ticker)
//Ask the event manager to print round end information
SSevents.RoundEnd()
+ //make big obvious note in game logs that round ended
+ log_game("///////////////////////////////////////////////////////")
+ log_game("///////////////////// ROUND ENDED /////////////////////")
+ log_game("///////////////////////////////////////////////////////")
+
// Add AntagHUD to everyone, see who was really evil the whole time!
for(var/datum/atom_hud/antag/H in GLOB.huds)
for(var/m in GLOB.player_list)
diff --git a/code/controllers/subsystem/tickets/mentor_tickets.dm b/code/controllers/subsystem/tickets/mentor_tickets.dm
index d8bae77840c..3fd003418a4 100644
--- a/code/controllers/subsystem/tickets/mentor_tickets.dm
+++ b/code/controllers/subsystem/tickets/mentor_tickets.dm
@@ -1,8 +1,8 @@
GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets)
/datum/controller/subsystem/tickets/mentor_tickets/New()
- NEW_SS_GLOBAL(SSmentor_tickets);
- PreInit();
+ NEW_SS_GLOBAL(SSmentor_tickets)
+ PreInit()
/datum/controller/subsystem/tickets/mentor_tickets
name = "Mentor Tickets"
@@ -10,12 +10,13 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
ticket_name = "Mentor Ticket"
span_class = "mentorhelp"
close_rights = R_MENTOR | R_ADMIN
+ offline_implications = "Mentor tickets will no longer be marked as stale. No immediate action is needed."
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
message_mentorTicket(msg)
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
- close_messages = list("- [ticket_name] Closed -",
- "Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.",
+ close_messages = list("- [ticket_name] Closed -",
+ "Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.",
"Your [ticket_name] has now been closed.")
return ..()
diff --git a/code/controllers/subsystem/tickets/tickets.dm b/code/controllers/subsystem/tickets/tickets.dm
index 058569250ec..8fae7179706 100644
--- a/code/controllers/subsystem/tickets/tickets.dm
+++ b/code/controllers/subsystem/tickets/tickets.dm
@@ -20,16 +20,17 @@ SUBSYSTEM_DEF(tickets)
init_order = INIT_ORDER_TICKETS
wait = 300
priority = FIRE_PRIORITY_TICKETS
-
+ offline_implications = "Admin tickets will no longer be marked as stale. No immediate action is needed."
+
flags = SS_BACKGROUND
-
+
var/list/allTickets = list() //make it here because someone might ahelp before the system has initialized
var/ticketCounter = 1
/datum/controller/subsystem/tickets/Initialize()
close_messages = list("- [ticket_name] Rejected! -",
- "Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.",
+ "Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.",
"Your [ticket_name] has now been closed.")
return ..()
@@ -112,7 +113,7 @@ SUBSYSTEM_DEF(tickets)
message_staff("[usr.client] / ([usr]) resolved [ticket_name] number [N]")
to_chat_safe(returnClient(N), "Your [ticket_name] has now been resolved.")
return TRUE
-
+
/datum/controller/subsystem/tickets/proc/autoRespond(N)
if(!check_rights(R_ADMIN|R_MOD))
@@ -124,19 +125,19 @@ SUBSYSTEM_DEF(tickets)
if(alert(usr, "[T.ticketState == TICKET_OPEN ? "Another admin appears to already be handling this." : "This ticket is already marked as closed or resolved"] Are you sure you want to continue?", "Confirmation", "Yes", "No") != "Yes")
return
T.assignStaff(C)
-
- var/response_phrases = list("Thanks" = "Thanks, have a Paradise day!",
+
+ var/response_phrases = list("Thanks" = "Thanks, have a Paradise day!",
"Handling It" = "The issue is being looked into, thanks.",
"Already Resolved" = "The problem has been resolved already.",
"Mentorhelp" = "Please redirect your question to Mentorhelp, as they are better experienced with these types of questions.",
"Happens Again" = "Thanks, let us know if it continues to happen.",
- "Clear Cache" = "To fix a blank screen, please leave the game and clear your Byond Cache. To clear your Byond Cache, there is a Settings icon in the top right of the launcher. After you click that, go into the Games tab and hit the Clear Cache button. If the issue persists a few minutes after rejoining and doing this, please adminhelp again and state you cleared your cache." ,
+ "Clear Cache" = "To fix a blank screen, go to the 'Special Verbs' tab and press 'Reload UI Resources'. If that fails, clear your BYOND cache (instructions provided with 'Reload UI Resources'). If that still fails, please adminhelp again, stating you have already done the following." ,
"IC Issue" = "This is an In Character (IC) issue and will not be handled by admins. You could speak to Security, Internal Affairs, a Departmental Head, Nanotrasen Representetive, or any other relevant authority currently on station.",
"Reject" = "Reject",
"Man Up" = "Man Up",
"Appeal on the Forums" = "Appealing a ban must occur on the forums. Privately messaging, or adminhelping about your ban will not resolve it. To appeal your ban, please head to [config.banappeals]"
)
-
+
var/sorted_responses = list()
for(var/key in response_phrases) //build a new list based on the short descriptive keys of the master list so we can send this as the input instead of the full paragraphs to the admin choosing which autoresponse
sorted_responses += key
@@ -351,7 +352,7 @@ UI STUFF
dat += "
"
if(!T.staffAssigned)
dat += "No staff member assigned to this [ticket_name] - Take Ticket "
@@ -447,7 +448,7 @@ UI STUFF
return
if(closeTicket(indexNum))
showDetailUI(usr, indexNum)
-
+
if(href_list["detailreopen"])
var/indexNum = text2num(href_list["detailreopen"])
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 1caa3d7819a..53d77e8fad6 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -9,6 +9,7 @@ SUBSYSTEM_DEF(timer)
init_order = INIT_ORDER_TIMER
flags = SS_TICKER|SS_NO_INIT
+ offline_implications = "The game will no longer process timers. Immediate server restart recommended."
var/list/second_queue = list() //awe, yes, you've had first queue, but what about second queue?
var/list/hashes = list()
@@ -159,7 +160,7 @@ SUBSYSTEM_DEF(timer)
if(timer.timeToRun < head_offset)
bucket_resolution = null //force bucket recreation
- CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+ stack_trace("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
if(timer.callBack && !timer.spent)
timer.callBack.InvokeAsync()
@@ -171,7 +172,7 @@ SUBSYSTEM_DEF(timer)
if(timer.timeToRun < head_offset + TICKS2DS(practical_offset-1))
bucket_resolution = null //force bucket recreation
- CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+ stack_trace("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
if(timer.callBack && !timer.spent)
timer.callBack.InvokeAsync()
spent += timer
diff --git a/code/modules/fancytitle/fancytitle.dm b/code/controllers/subsystem/titlescreen.dm
similarity index 85%
rename from code/modules/fancytitle/fancytitle.dm
rename to code/controllers/subsystem/titlescreen.dm
index d1cf08ff58c..e597f74e05f 100644
--- a/code/modules/fancytitle/fancytitle.dm
+++ b/code/controllers/subsystem/titlescreen.dm
@@ -1,4 +1,9 @@
-/hook/startup/proc/setup_title_screen()
+SUBSYSTEM_DEF(title)
+ name = "Title Screen"
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_TITLE
+
+/datum/controller/subsystem/title/Initialize()
var/list/provisional_title_screens = flist("config/title_screens/images/")
var/list/title_screens = list()
var/use_rare_screens = prob(1)
@@ -29,5 +34,5 @@
for(var/turf/unsimulated/wall/splashscreen/splash in world)
splash.icon = icon
- return TRUE
- return FALSE
+
+ return ..()
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 28456c9b5c5..0b91e6b3467 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(vote)
wait = 10
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ offline_implications = "Votes (Endround shuttle) will no longer function. Shuttle call recommended."
var/initiator = null
var/started_time = null
@@ -366,7 +367,7 @@ SUBSYSTEM_DEF(vote)
var/votedesc = capitalize(mode)
if(mode == "custom")
votedesc += " ([question])"
- admin_log_and_message_admins("cancelled the running [votedesc] vote.")
+ log_and_message_admins("cancelled the running [votedesc] vote.")
reset()
if("toggle_restart")
if(admin)
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index ac2f0c59313..30186f80ad1 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -9,6 +9,7 @@ SUBSYSTEM_DEF(weather)
flags = SS_BACKGROUND
wait = 10
runlevels = RUNLEVEL_GAME
+ offline_implications = "Ash storms will no longer trigger. No immediate action is needed."
var/list/processing = list()
var/list/eligible_zlevels = list()
var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming
@@ -19,7 +20,7 @@ SUBSYSTEM_DEF(weather)
var/datum/weather/W = V
if(W.aesthetic || W.stage != MAIN_STAGE)
continue
- for(var/i in GLOB.living_mob_list)
+ for(var/i in GLOB.mob_living_list)
var/mob/living/L = i
if(W.can_weather_act(L))
W.weather_act(L)
@@ -56,7 +57,6 @@ SUBSYSTEM_DEF(weather)
break
if(!ispath(weather_datum_type, /datum/weather))
CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]")
- return
if(isnull(z_levels))
z_levels = levels_by_trait(initial(weather_datum_type.target_trait))
@@ -64,7 +64,6 @@ SUBSYSTEM_DEF(weather)
z_levels = list(z_levels)
else if(!islist(z_levels))
CRASH("run_weather called with invalid z_levels: [z_levels || "null"]")
- return
var/datum/weather/W = new weather_datum_type(z_levels)
W.telegraph()
diff --git a/code/datums/action.dm b/code/datums/action.dm
index b7af84e9ddf..c1802da47c1 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -339,7 +339,7 @@
/datum/action/item_action/remove_tape/Trigger(attack_self = FALSE)
if(..())
- GET_COMPONENT_FROM(DT, /datum/component/ducttape, target)
+ var/datum/component/ducttape/DT = target.GetComponent(/datum/component/ducttape)
DT.remove_tape(target, usr)
/datum/action/item_action/toggle_jetpack
diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index 0a14b0e9476..8e1a9d8bcce 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -62,15 +62,15 @@
if(sorted_laws.len)
return
- for(var/ion_law in ion_laws)
- sorted_laws += ion_law
-
- for(var/evil_law in devil_laws)
- sorted_laws += evil_law
-
if(zeroth_law)
sorted_laws += zeroth_law
+ for(var/ion_law in ion_laws)
+ sorted_laws += ion_law
+
+ for(var/evil_law in devil_laws)
+ sorted_laws += evil_law
+
var/index = 1
for(var/datum/ai_law/inherent_law in inherent_laws)
inherent_law.index = index++
@@ -133,12 +133,12 @@
for(var/datum/ai_law/AL in devil_laws)
if(AL.law == law)
return
-
+
var/new_law = new/datum/ai_law/sixsixsix(law)
devil_laws += new_law
if(state_devil.len < devil_laws.len)
state_devil += 1
-
+
sorted_laws.Cut()
/datum/ai_laws/proc/add_ion_law(var/law)
@@ -209,9 +209,9 @@
/datum/ai_law/ion/delete_law(var/datum/ai_laws/laws)
laws.internal_delete_law(laws.ion_laws, laws.state_ion, src)
-
+
/datum/ai_law/sixsixsix/delete_law(var/datum/ai_laws/laws)
- laws.internal_delete_law(laws.devil_laws, laws.state_devil, src)
+ laws.internal_delete_law(laws.devil_laws, laws.state_devil, src)
/datum/ai_law/inherent/delete_law(var/datum/ai_laws/laws)
laws.internal_delete_law(laws.inherent_laws, laws.state_inherent, src)
diff --git a/code/datums/armor.dm b/code/datums/armor.dm
new file mode 100644
index 00000000000..0de7dde1ee7
--- /dev/null
+++ b/code/datums/armor.dm
@@ -0,0 +1,69 @@
+#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
+
+/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
+ . = locate(ARMORID)
+ if (!.)
+ . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
+
+/datum/armor
+ var/melee
+ var/bullet
+ var/laser
+ var/energy
+ var/bomb
+ var/bio
+ var/rad
+ var/fire
+ var/acid
+ var/magic
+
+/datum/armor/New(melee_value = 0, bullet_value = 0, laser_value = 0, energy_value = 0, bomb_value = 0, bio_value = 0, rad_value = 0, fire_value = 0, acid_value = 0, magic_value = 0)
+ melee = melee_value
+ bullet = bullet_value
+ laser = laser_value
+ energy = energy_value
+ bomb = bomb_value
+ bio = bio_value
+ rad = rad_value
+ fire = fire_value
+ acid = acid_value
+ magic = magic_value
+ tag = ARMORID
+
+/datum/armor/proc/modifyRating(melee_value = 0, bullet_value = 0, laser_value = 0, energy_value = 0, bomb_value = 0, bio_value = 0, rad_value = 0, fire_value = 0, acid_value = 0, magic_value = 0)
+ return getArmor(melee + melee_value, bullet + bullet_value, laser + laser_value, energy + energy_value, bomb + bomb_value, bio + bio_value, rad + rad_value, fire + fire_value, acid + acid_value, magic + magic_value)
+
+/datum/armor/proc/modifyAllRatings(modifier = 0)
+ return getArmor(melee + modifier, bullet + modifier, laser + modifier, energy + modifier, bomb + modifier, bio + modifier, rad + modifier, fire + modifier, acid + modifier, magic + modifier)
+
+/datum/armor/proc/setRating(melee_value, bullet_value, laser_value, energy_value, bomb_value, bio_value, rad_value, fire_value, acid_value, magic_value)
+ return getArmor((isnull(melee_value) ? melee : melee_value),\
+ (isnull(bullet_value) ? bullet : bullet_value),\
+ (isnull(laser_value) ? laser : laser_value),\
+ (isnull(energy_value) ? energy : energy_value),\
+ (isnull(bomb_value) ? bomb : bomb_value),\
+ (isnull(bio_value) ? bio : bio_value),\
+ (isnull(rad_value) ? rad : rad_value),\
+ (isnull(fire_value) ? fire : fire_value),\
+ (isnull(acid_value) ? acid : acid_value),\
+ (isnull(magic_value) ? magic : magic_value))
+
+/datum/armor/proc/getRating(rating)
+ return vars[rating]
+
+/datum/armor/proc/getList()
+ return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
+
+/datum/armor/proc/attachArmor(datum/armor/AA)
+ return getArmor(melee + AA.melee, bullet + AA.bullet, laser + AA.laser, energy + AA.energy, bomb + AA.bomb, bio + AA.bio, rad + AA.rad, fire + AA.fire, acid + AA.acid, magic + AA.magic)
+
+/datum/armor/proc/detachArmor(datum/armor/AA)
+ return getArmor(melee - AA.melee, bullet - AA.bullet, laser - AA.laser, energy - AA.energy, bomb - AA.bomb, bio - AA.bio, rad - AA.rad, fire - AA.fire, acid - AA.acid, magic - AA.magic)
+
+/datum/armor/vv_edit_var(var_name, var_value)
+ if (var_name == NAMEOF(src, tag))
+ return FALSE
+ . = ..()
+ tag = ARMORID // update tag in case armor values were edited
+
+#undef ARMORID
diff --git a/code/datums/beam.dm b/code/datums/beam.dm
index 86f816662c0..3b5c9d2f5fb 100644
--- a/code/datums/beam.dm
+++ b/code/datums/beam.dm
@@ -99,11 +99,11 @@
//Position the effect so the beam is one continous line
var/a
if(abs(Pixel_x)>32)
- a = Pixel_x > 0 ? round(Pixel_x/32) : Ceiling(Pixel_x/32)
+ a = Pixel_x > 0 ? round(Pixel_x/32) : CEILING(Pixel_x/32, 1)
X.x += a
Pixel_x %= 32
if(abs(Pixel_y)>32)
- a = Pixel_y > 0 ? round(Pixel_y/32) : Ceiling(Pixel_y/32)
+ a = Pixel_y > 0 ? round(Pixel_y/32) : CEILING(Pixel_y/32, 1)
X.y += a
Pixel_y %= 32
@@ -131,6 +131,5 @@
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
- spawn(0)
- newbeam.Start()
+ INVOKE_ASYNC(newbeam, /datum/beam.proc/Start)
return newbeam
diff --git a/code/datums/cache/crew.dm b/code/datums/cache/crew.dm
index 21ec5ebcc79..f92bab9cf7a 100644
--- a/code/datums/cache/crew.dm
+++ b/code/datums/cache/crew.dm
@@ -4,7 +4,7 @@ GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
cache_data = list()
..()
-/datum/repository/crew/proc/health_data(var/turf/T)
+/datum/repository/crew/proc/health_data(turf/T)
var/list/crewmembers = list()
if(!T)
return crewmembers
@@ -18,50 +18,40 @@ GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
if(world.time < cache_entry.timestamp)
return cache_entry.data
- var/tracked = scan()
- for(var/obj/item/clothing/under/C in tracked)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ var/obj/item/clothing/under/C = H.w_uniform
+ if(!C || C.sensor_mode == SUIT_SENSOR_OFF || !C.has_sensor)
+ continue
var/turf/pos = get_turf(C)
- if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
- if(istype(C.loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = C.loc
- if(H.w_uniform != C)
- continue
+ if(!T || pos.z != T.z)
+ continue
+ var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1, "ref" = "\ref[H]")
- var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1, "ref" = "\ref[H]")
+ crewmemberData["sensor_type"] = C.sensor_mode
+ crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
+ crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
+ crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
- crewmemberData["sensor_type"] = C.sensor_mode
- crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
- crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
- crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
+ if(C.sensor_mode >= SUIT_SENSOR_BINARY)
+ crewmemberData["dead"] = H.stat > UNCONSCIOUS
- if(C.sensor_mode >= SUIT_SENSOR_BINARY)
- crewmemberData["dead"] = H.stat > UNCONSCIOUS
+ if(C.sensor_mode >= SUIT_SENSOR_VITAL)
+ crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
+ crewmemberData["tox"] = round(H.getToxLoss(), 1)
+ crewmemberData["fire"] = round(H.getFireLoss(), 1)
+ crewmemberData["brute"] = round(H.getBruteLoss(), 1)
- if(C.sensor_mode >= SUIT_SENSOR_VITAL)
- crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
- crewmemberData["tox"] = round(H.getToxLoss(), 1)
- crewmemberData["fire"] = round(H.getFireLoss(), 1)
- crewmemberData["brute"] = round(H.getBruteLoss(), 1)
+ if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
+ var/area/A = get_area(H)
+ crewmemberData["area"] = sanitize(A.name)
+ crewmemberData["x"] = pos.x
+ crewmemberData["y"] = pos.y
- if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
- var/area/A = get_area(H)
- crewmemberData["area"] = sanitize(A.name)
- crewmemberData["x"] = pos.x
- crewmemberData["y"] = pos.y
-
- crewmembers[++crewmembers.len] = crewmemberData
+ crewmembers[++crewmembers.len] = crewmemberData
crewmembers = sortByKey(crewmembers, "name")
cache_entry.timestamp = world.time + 5 SECONDS
cache_entry.data = crewmembers
return crewmembers
-
-/datum/repository/crew/proc/scan()
- var/list/tracked = list()
- for(var/mob/living/carbon/human/H in GLOB.mob_list)
- if(istype(H.w_uniform, /obj/item/clothing/under))
- var/obj/item/clothing/under/C = H.w_uniform
- if(C.has_sensor)
- tracked |= C
- return tracked
diff --git a/code/datums/components/README.md b/code/datums/components/README.md
index 9d06a255dd7..03f7d3a5875 100644
--- a/code/datums/components/README.md
+++ b/code/datums/components/README.md
@@ -2,134 +2,8 @@
## Concept
-Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SEND_SIGNAL` call. Now every component that want's to can also know about this happening.
+Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening.
-### In the code
+See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole.
-#### Slippery things
-
-At the time of this writing, every object that is slippery overrides atom/Crossed does some checks, then slips the mob. Instead of all those Crossed overrides they could add a slippery component to all these objects. And have the checks in one proc that is run by the Crossed event
-
-#### Powercells
-
-A lot of objects have powercells. The `get_cell()` proc was added to give generic access to the cell var if it had one. This is just a specific use case of `GetComponent()`
-
-#### Radios
-
-The radio object as it is should not exist, given that more things use the _concept_ of radios rather than the object itself. The actual function of the radio can exist in a component which all the things that use it (Request consoles, actual radios, the SM shard) can add to themselves.
-
-#### Standos
-
-Stands have a lot of procs which mimic mob procs. Rather than inserting hooks for all these procs in overrides, the same can be accomplished with signals
-
-## API
-
-### Defines
-
-1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs
-
-### Vars
-
-1. `/datum/var/list/datum_components` (private)
- * Lazy associated list of type -> component/list of components.
-1. `/datum/var/list/comp_lookup` (private)
- * Lazy associated list of signal -> registree/list of registrees
-1. `/datum/var/list/signal_procs` (private)
- * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal
-1. `/datum/var/signal_enabled` (protected, boolean)
- * If the datum is signal enabled. If not, it will not react to signals
- * `FALSE` by default, set to `TRUE` when a signal is registered
-1. `/datum/component/var/dupe_mode` (protected, enum)
- * How duplicate component types are handled when added to the datum.
- * `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
- * `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added
- * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it
- * `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component.
-1. `/datum/component/var/dupe_type` (protected, type)
- * Definition of a duplicate component type
- * `null` means exact match on `type` (default)
- * Any other type means that and all subtypes
-1. `/datum/component/var/datum/parent` (protected, read-only)
- * The datum this component belongs to
- * Never `null` in child procs
-1. `report_signal_origin` (protected, boolean)
- * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument.
- * `FALSE` by default.
-
-### Procs
-
-1. `/datum/proc/GetComponent(component_type(type)) -> datum/component?` (public, final)
- * Returns a reference to a component of component_type if it exists in the datum, null otherwise
-1. `/datum/proc/GetComponents(component_type(type)) -> list` (public, final)
- * Returns a list of references to all components of component_type that exist in the datum
-1. `/datum/proc/GetExactComponent(component_type(type)) -> datum/component?` (public, final)
- * Returns a reference to a component whose type MATCHES component_type if that component exists in the datum, null otherwise
-1. `GET_COMPONENT(varname, component_type)` OR `GET_COMPONENT_FROM(varname, component_type, src)`
- * Shorthand for `var/component_type/varname = src.GetComponent(component_type)`
-1. `SEND_SIGNAL(target, sigtype, ...)` (public, final)
- * Use to send signals to target datum
- * Extra arguments are to be specified in the signal definition
- * Returns a bitflag with signal specific information assembled from all activated components
- * Arguments are packaged in a list and handed off to _SendSignal()
-1. `/datum/proc/AddComponent(component_type(type), ...) -> datum/component` (public, final)
- * Creates an instance of `component_type` in the datum and passes `...` to its `Initialize()` call
- * Sends the `COMSIG_COMPONENT_ADDED` signal to the datum
- * All components a datum owns are deleted with the datum
- * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
- * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
- * Properly handles duplicate situations based on the `dupe_mode` var
-1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
- * Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
-1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
- * Called on a component's `parent` after a signal received causes it to activate. `src` is the parameter
- * Will only be called if a component's callback returns `TRUE`
-1. `/datum/proc/TakeComponent(datum/component/C)` (public, final)
- * Properly transfers ownership of a component from one datum to another
- * Signals `COMSIG_COMPONENT_REMOVING` on the parent
- * Called on the datum you want to own the component with another datum's component
-1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final)
- * Handles most of the actual signaling procedure
- * Will runtime if used on datums with an empty component list
-1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final)
- * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
- * Makes the datum listen for the specified `signal` on it's `parent` datum.
- * When that signal is received `proc_ref` will be called on the component, along with associated arguments
- * Example proc ref: `.proc/OnEvent`
- * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
- * These callbacks run asyncronously
- * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
-1. `/datum/component/New(datum/parent, ...)` (private, final)
- * Runs internal setup for the component
- * Extra arguments are passed to `Initialize()`
-1. `/datum/component/Initialize(...)` (abstract, no-sleep)
- * Called by `New()` with the same argments excluding `parent`
- * Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used
- * Signals will not be received while this function is running
- * Component may be deleted after this function completes without being attached
- * Do not call `qdel(src)` from this function
-1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep)
- * Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted
- * Properly removes the component from `parent` and cleans up references
- * Setting `force` makes it not check for and remove the component from the parent
- * Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal
-1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep)
- * Called on a component when a component of the same type was added to the same parent
- * See `/datum/component/var/dupe_mode`
- * `C`'s type will always be the same of the called component
-1. `/datum/component/proc/AfterComponentActivated()` (abstract, async)
- * Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called
-1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep)
- * Called before `new_parent` is assigned to `parent` in `TakeComponent()`
- * Allows the component to react to ownership transfers
-1. `/datum/component/proc/_RemoveFromParent()` (private, final)
- * Clears `parent` and removes the component from it's component list
-1. `/datum/component/proc/_JoinParent` (private, final)
- * Tries to add the component to it's `parent`s `datum_components` list
-1. `/datum/component/proc/RegisterWithParent` (abstract, no-sleep)
- * Used to register the signals that should be on the `parent` object
- * Use this if you plan on the component transfering between parents
-1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep)
- * Counterpart to `RegisterWithParent()`
- * Used to unregister the signals that should only be on the `parent` object
-
-### See/Define signals and their arguments in __DEFINES\components.dm
+### See/Define signals and their arguments in [__DEFINES\dcs\signals.dm](../../__DEFINES/dcs/signals.dm)
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index e733ca78d2b..f895b8d81b1 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -1,21 +1,87 @@
+/**
+ * # Component
+ *
+ * The component datum
+ *
+ * A component should be a single standalone unit
+ * of functionality, that works by receiving signals from it's parent
+ * object to provide some single functionality (i.e a slippery component)
+ * that makes the object it's attached to cause people to slip over.
+ * Useful when you want shared behaviour independent of type inheritance
+ */
/datum/component
+ /**
+ * Defines how duplicate existing components are handled when added to a datum
+ *
+ * See [COMPONENT_DUPE_*][COMPONENT_DUPE_ALLOWED] definitions for available options
+ */
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
+
+ /**
+ * The type to check for duplication
+ *
+ * `null` means exact match on `type` (default)
+ *
+ * Any other type means that and all subtypes
+ */
var/dupe_type
+
+ /// The datum this components belongs to
var/datum/parent
- //only set to true if you are able to properly transfer this component
- //At a minimum RegisterWithParent and UnregisterFromParent should be used
- //Make sure you also implement PostTransfer for any post transfer handling
+
+ /**
+ * Only set to true if you are able to properly transfer this component
+ *
+ * At a minimum [RegisterWithParent][/datum/component/proc/RegisterWithParent] and [UnregisterFromParent][/datum/component/proc/UnregisterFromParent] should be used
+ *
+ * Make sure you also implement [PostTransfer][/datum/component/proc/PostTransfer] for any post transfer handling
+ */
var/can_transfer = FALSE
-/datum/component/New(datum/P, ...)
- parent = P
- var/list/arguments = args.Copy(2)
+/**
+ * Create a new component.
+ *
+ * Additional arguments are passed to [Initialize()][/datum/component/proc/Initialize]
+ *
+ * Arguments:
+ * * datum/P the parent datum this component reacts to signals from
+ */
+/datum/component/New(list/raw_args)
+ parent = raw_args[1]
+ var/list/arguments = raw_args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
+ stack_trace("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]")
qdel(src, TRUE, TRUE)
- CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]")
+ return
- _JoinParent(P)
+ _JoinParent(parent)
+/**
+ * Called during component creation with the same arguments as in new excluding parent.
+ *
+ * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead
+ */
+/datum/component/proc/Initialize(...)
+ return
+
+/**
+ * Properly removes the component from `parent` and cleans up references
+ *
+ * Arguments:
+ * * force - makes it not check for and remove the component from the parent
+ * * silent - deletes the component without sending a [COMSIG_COMPONENT_REMOVING] signal
+ */
+/datum/component/Destroy(force=FALSE, silent=FALSE)
+ if(!force && parent)
+ _RemoveFromParent()
+ if(!silent)
+ SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src)
+ parent = null
+ return ..()
+
+/**
+ * Internal proc to handle behaviour of components when joining a parent
+ */
/datum/component/proc/_JoinParent()
var/datum/P = parent
//lazy init the parent's dc list
@@ -51,21 +117,9 @@
RegisterWithParent()
-// If you want/expect to be moving the component around between parents, use this to register on the parent for signals
-/datum/component/proc/RegisterWithParent()
- return
-
-/datum/component/proc/Initialize(...)
- return
-
-/datum/component/Destroy(force=FALSE, silent=FALSE)
- if(!force && parent)
- _RemoveFromParent()
- if(!silent)
- SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src)
- parent = null
- return ..()
-
+/**
+ * Internal proc to handle behaviour when being removed from a parent
+ */
/datum/component/proc/_RemoveFromParent()
var/datum/P = parent
var/list/dc = P.datum_components
@@ -84,10 +138,41 @@
UnregisterFromParent()
+/**
+ * Register the component with the parent object
+ *
+ * Use this proc to register with your parent object
+ *
+ * Overridable proc that's called when added to a new parent
+ */
+/datum/component/proc/RegisterWithParent()
+ return
+
+/**
+ * Unregister from our parent object
+ *
+ * Use this proc to unregister from your parent object
+ *
+ * Overridable proc that's called when removed from a parent
+ * *
+ */
/datum/component/proc/UnregisterFromParent()
return
-/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
+/**
+ * Register to listen for a signal from the passed in target
+ *
+ * This sets up a listening relationship such that when the target object emits a signal
+ * the source datum this proc is called upon, will recieve a callback to the given proctype
+ * Return values from procs registered must be a bitfield
+ *
+ * Arguments:
+ * * datum/target The target to listen for signals from
+ * * sig_type_or_types Either a string signal name, or a list of signal names (strings)
+ * * proctype The proc to call back when the signal is emitted
+ * * override If a previous registration exists you must explicitly set this
+ */
+/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE)
if(QDELETED(src) || QDELETED(target))
return
@@ -100,15 +185,12 @@
if(!lookup)
target.comp_lookup = lookup = list()
- if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
- proc_or_callback = CALLBACK(src, proc_or_callback)
-
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
for(var/sig_type in sig_types)
if(!override && procs[target][sig_type])
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
- procs[target][sig_type] = proc_or_callback
+ procs[target][sig_type] = proctype
if(!lookup[sig_type]) // Nothing has registered here yet
lookup[sig_type] = src
@@ -122,6 +204,17 @@
signal_enabled = TRUE
+/**
+ * Stop listening to a given signal from target
+ *
+ * Breaks the relationship between target and source datum, removing the callback when the signal fires
+ *
+ * Doesn't care if a registration exists or not
+ *
+ * Arguments:
+ * * datum/target Datum to stop listening to signals from
+ * * sig_typeor_types Signal string key or list of signal keys to stop listening to specifically
+ */
/datum/proc/UnregisterSignal(datum/target, sig_type_or_types)
var/list/lookup = target.comp_lookup
if(!signal_procs || !signal_procs[target] || !lookup)
@@ -129,6 +222,8 @@
if(!islist(sig_type_or_types))
sig_type_or_types = list(sig_type_or_types)
for(var/sig in sig_type_or_types)
+ if(!signal_procs[target][sig])
+ continue
switch(length(lookup[sig]))
if(2)
lookup[sig] = (lookup[sig]-src)[1]
@@ -151,41 +246,96 @@
if(!signal_procs[target].len)
signal_procs -= target
+/**
+ * Called on a component when a component of the same type was added to the same parent
+ *
+ * See [/datum/component/var/dupe_mode]
+ *
+ * `C`'s type will always be the same of the called component
+ */
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
return
+
+/**
+ * Called on a component when a component of the same type was added to the same parent with [COMPONENT_DUPE_SELECTIVE]
+ *
+ * See [/datum/component/var/dupe_mode]
+ *
+ * `C`'s type will always be the same of the called component
+ *
+ * return TRUE if you are absorbing the component, otherwise FALSE if you are fine having it exist as a duplicate component
+ */
+/datum/component/proc/CheckDupeComponent(datum/component/C, ...)
+ return
+
+
+/**
+ * Callback Just before this component is transferred
+ *
+ * Use this to do any special cleanup you might need to do before being deregged from an object
+ */
/datum/component/proc/PreTransfer()
return
+/**
+ * Callback Just after a component is transferred
+ *
+ * Use this to do any special setup you need to do after being moved to a new object
+ *
+ * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead
+ */
/datum/component/proc/PostTransfer()
return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it
+/**
+ * Internal proc to create a list of our type and all parent types
+ */
/datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick
var/current_type = parent_type
. = list(our_type, current_type)
//and since most components are root level + 1, this won't even have to run
- while(current_type != /datum/component)
+ while (current_type != /datum/component)
current_type = type2parent(current_type)
. += current_type
+/**
+ * Internal proc to handle most all of the signaling procedure
+ *
+ * Will runtime if used on datums with an empty component list
+ *
+ * Use the [SEND_SIGNAL] define instead
+ */
/datum/proc/_SendSignal(sigtype, list/arguments)
var/target = comp_lookup[sigtype]
if(!length(target))
var/datum/C = target
if(!C.signal_enabled)
return NONE
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- return CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ return NONE | CallAsync(C, proctype, arguments)
. = NONE
for(var/I in target)
var/datum/C = I
if(!C.signal_enabled)
continue
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- . |= CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ . |= CallAsync(C, proctype, arguments)
-/datum/proc/GetComponent(c_type)
+// The type arg is casted so initial works, you shouldn't be passing a real instance into this
+/**
+ * Return any component assigned to this datum of the given type
+ *
+ * This will throw an error if it's possible to have more than one component of that type on the parent
+ *
+ * Arguments:
+ * * datum/component/c_type The typepath of the component you want to get a reference to
+ */
+/datum/proc/GetComponent(datum/component/c_type)
+ RETURN_TYPE(c_type)
+ if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE)
+ stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
var/list/dc = datum_components
if(!dc)
return null
@@ -193,7 +343,19 @@
if(length(.))
return .[1]
-/datum/proc/GetExactComponent(c_type)
+// The type arg is casted so initial works, you shouldn't be passing a real instance into this
+/**
+ * Return any component assigned to this datum of the exact given type
+ *
+ * This will throw an error if it's possible to have more than one component of that type on the parent
+ *
+ * Arguments:
+ * * datum/component/c_type The typepath of the component you want to get a reference to
+ */
+/datum/proc/GetExactComponent(datum/component/c_type)
+ RETURN_TYPE(c_type)
+ if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE)
+ stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
var/list/dc = datum_components
if(!dc)
return null
@@ -205,6 +367,12 @@
return C
return null
+/**
+ * Get all components of a given type that are attached to this datum
+ *
+ * Arguments:
+ * * c_type The component type path
+ */
/datum/proc/GetComponents(c_type)
var/list/dc = datum_components
if(!dc)
@@ -213,7 +381,19 @@
if(!length(.))
return list(.)
-/datum/proc/AddComponent(new_type, ...)
+/**
+ * Creates an instance of `new_type` in the datum and attaches to it as parent
+ *
+ * Sends the [COMSIG_COMPONENT_ADDED] signal to the datum
+ *
+ * Returns the component that was created. Or the old component in a dupe situation where [COMPONENT_DUPE_UNIQUE] was set
+ *
+ * If this tries to add a component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
+ *
+ * Properly handles duplicate situations based on the `dupe_mode` var
+ */
+/datum/proc/_AddComponent(list/raw_args)
+ var/new_type = raw_args[1]
var/datum/component/nt = new_type
var/dm = initial(nt.dupe_mode)
var/dt = initial(nt.dupe_type)
@@ -228,7 +408,7 @@
new_comp = nt
nt = new_comp.type
- args[1] = src
+ raw_args[1] = src
if(dm != COMPONENT_DUPE_ALLOWED)
if(!dt)
@@ -239,37 +419,62 @@
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
if(!new_comp)
- new_comp = new nt(arglist(args))
+ new_comp = new nt(raw_args)
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
QDEL_NULL(new_comp)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
- new_comp = new nt(arglist(args))
+ new_comp = new nt(raw_args)
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
QDEL_NULL(old_comp)
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
- var/list/arguments = args.Copy(2)
- old_comp.InheritComponent(null, TRUE, arguments)
+ var/list/arguments = raw_args.Copy(2)
+ arguments.Insert(1, null, TRUE)
+ old_comp.InheritComponent(arglist(arguments))
else
old_comp.InheritComponent(new_comp, TRUE)
+ if(COMPONENT_DUPE_SELECTIVE)
+ var/list/arguments = raw_args.Copy()
+ arguments[1] = new_comp
+ var/make_new_component = TRUE
+ for(var/i in GetComponents(new_type))
+ var/datum/component/C = i
+ if(C.CheckDupeComponent(arglist(arguments)))
+ make_new_component = FALSE
+ QDEL_NULL(new_comp)
+ break
+ if(!new_comp && make_new_component)
+ new_comp = new nt(raw_args)
else if(!new_comp)
- new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal
+ new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal
else if(!new_comp)
- new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal
+ new_comp = new nt(raw_args) // Dupes are allowed, act like normal
if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy
SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp)
return new_comp
return old_comp
+/**
+ * Get existing component of type, or create it and return a reference to it
+ *
+ * Use this if the item needs to exist at the time of this call, but may not have been created before now
+ *
+ * Arguments:
+ * * component_type The typepath of the component to create or return
+ * * ... additional arguments to be passed when creating the component if it does not exist
+ */
/datum/proc/LoadComponent(component_type, ...)
. = GetComponent(component_type)
if(!.)
- return AddComponent(arglist(args))
+ return _AddComponent(args)
+/**
+ * Removes the component from parent, ends up with a null parent
+ */
/datum/component/proc/RemoveComponent()
if(!parent)
return
@@ -279,6 +484,14 @@
parent = null
SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src)
+/**
+ * Transfer this component to another parent
+ *
+ * Component is taken from source datum
+ *
+ * Arguments:
+ * * datum/component/target Target datum to transfer to
+ */
/datum/proc/TakeComponent(datum/component/target)
if(!target || target.parent == src)
return
@@ -295,6 +508,14 @@
if(target == AddComponent(target))
target._JoinParent()
+/**
+ * Transfer all components to target
+ *
+ * All components from source datum are taken
+ *
+ * Arguments:
+ * * /datum/target the target to move the components to
+ */
/datum/proc/TransferComponents(datum/target)
var/list/dc = datum_components
if(!dc)
@@ -309,5 +530,8 @@
if(C.can_transfer)
target.TakeComponent(comps)
+/**
+ * Return the object that is the host of any UI's that this component has
+ */
/datum/component/nano_host()
return parent
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
index 6a0f686b13a..876cf0c0507 100644
--- a/code/datums/components/decal.dm
+++ b/code/datums/components/decal.dm
@@ -7,7 +7,7 @@
var/first_dir // This only stores the dir arg from init
-/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
+/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable = CLEAN_GOD, _color, _layer = TURF_LAYER, _description, _alpha = 255)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
return COMPONENT_INCOMPATIBLE
first_dir = _dir
diff --git a/code/datums/components/ducttape.dm b/code/datums/components/ducttape.dm
index 98512589a46..49931db8edc 100644
--- a/code/datums/components/ducttape.dm
+++ b/code/datums/components/ducttape.dm
@@ -37,10 +37,10 @@
I.anchored = initial(I.anchored)
for(var/datum/action/item_action/remove_tape/RT in I.actions)
RT.Remove(user)
- RT.Destroy()
+ qdel(RT)
I.overlays.Cut(tape_overlay)
user.transfer_fingerprints_to(I)
- Destroy()
+ qdel(src)
/datum/component/ducttape/proc/afterattack(obj/item/I, atom/target, mob/user, proximity, params)
if(!proximity)
diff --git a/code/datums/components/edit_complainer.dm b/code/datums/components/edit_complainer.dm
new file mode 100644
index 00000000000..7910515cb45
--- /dev/null
+++ b/code/datums/components/edit_complainer.dm
@@ -0,0 +1,23 @@
+// This is just a bit of fun while making an example for global signal
+/datum/component/edit_complainer
+ var/list/say_lines
+
+/datum/component/edit_complainer/Initialize(list/text)
+ if(!ismovable(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/static/list/default_lines = list(
+ "CentComm's profligacy frays another thread.",
+ "Another tug at the weave.",
+ "Who knows when the stresses will finally shatter the form?",
+ "Even now a light shines through the cracks.",
+ "CentComm once more twists knowledge beyond its authority.",
+ "There is an uncertain air in the mansus.",
+ )
+ say_lines = text || default_lines
+
+ RegisterSignal(SSdcs, COMSIG_GLOB_VAR_EDIT, .proc/var_edit_react)
+
+/datum/component/edit_complainer/proc/var_edit_react(datum/source, list/arguments)
+ var/atom/movable/master = parent
+ master.atom_say(pick(say_lines))
diff --git a/code/datums/components/jestosterone.dm b/code/datums/components/jestosterone.dm
deleted file mode 100644
index f37f1f03efb..00000000000
--- a/code/datums/components/jestosterone.dm
+++ /dev/null
@@ -1,5 +0,0 @@
-/datum/component/jestosterone
- var/mind_type //Is the affected mob a clown / mime?
-
-/datum/component/jestosterone/Initialize(mind_type_arg)
- mind_type = mind_type_arg
diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm
new file mode 100644
index 00000000000..c6d0c595ebb
--- /dev/null
+++ b/code/datums/components/label.dm
@@ -0,0 +1,87 @@
+/**
+ The label component.
+
+ This component is used to manage labels applied by the hand labeler.
+
+ Atoms can only have one instance of this component, and therefore only one label at a time.
+ This is to avoid having names like "Backpack (label1) (label2) (label3)". This is annoying and abnoxious to read.
+
+ When a player clicks the atom with a hand labeler to apply a label, this component gets applied to it.
+ If the labeler is off, the component will be removed from it, and the label will be removed from its name.
+ */
+/datum/component/label
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ /// The name of the label the player is applying to the parent.
+ var/label_name
+
+/datum/component/label/Initialize(_label_name)
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ label_name = _label_name
+ apply_label()
+
+/datum/component/label/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackby)
+ RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/Examine)
+
+/datum/component/label/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE))
+
+/**
+ This proc will fire after the parent is hit by a hand labeler which is trying to apply another label.
+ Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one.
+*/
+/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, _label_name)
+ remove_label()
+ if(new_comp)
+ label_name = new_comp.label_name
+ else
+ label_name = _label_name
+ apply_label()
+
+/**
+ This proc will trigger when any object is used to attack the parent.
+
+ If the attacking object is not a hand labeler, it will return.
+ If the attacking object is a hand labeler it will restore the name of the parent to what it was before this component was added to it, and the component will be deleted.
+
+ Arguments:
+ * source: The parent.
+ * attacker: The object that is hitting the parent.
+ * user: The mob who is wielding the attacking object.
+*/
+/datum/component/label/proc/OnAttackby(datum/source, obj/item/attacker, mob/user)
+ // If the attacking object is not a hand labeler or its mode is 1 (has a label ready to apply), return.
+ // The hand labeler should be off (mode is 0), in order to remove a label.
+ var/obj/item/hand_labeler/labeler = attacker
+ if(!istype(labeler) || labeler.mode)
+ return
+
+ remove_label()
+ playsound(parent, 'sound/items/poster_ripped.ogg', 20, TRUE)
+ to_chat(user, "You remove the label from [parent].")
+ qdel(src) // Remove the component from the object.
+
+/**
+ This proc will trigger when someone examines the parent.
+ It will attach the text found in the body of the proc to the `examine_list` and display it to the player examining the parent.
+
+ Arguments:
+ * source: The parent.
+ * user: The mob exmaining the parent.
+ * examine_list: The current list of text getting passed from the parent's normal examine() proc.
+*/
+/datum/component/label/proc/Examine(datum/source, mob/user, list/examine_list)
+ examine_list += "It has a label with some words written on it. Use a hand labeler to remove it."
+
+/// Applies a label to the name of the parent in the format of: "parent_name (label)"
+/datum/component/label/proc/apply_label()
+ var/atom/owner = parent
+ owner.name += " ([label_name])"
+
+/// Removes the label from the parent's name
+/datum/component/label/proc/remove_label()
+ var/atom/owner = parent
+ owner.name = replacetext(owner.name, "([label_name])", "") // Remove the label text from the parent's name, wherever it's located.
+ owner.name = trim(owner.name) // Shave off any white space from the beginning or end of the parent's name.
diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm
new file mode 100644
index 00000000000..88e51209afb
--- /dev/null
+++ b/code/datums/components/slippery.dm
@@ -0,0 +1,56 @@
+/**
+ * # Slip Component
+ *
+ * This is a component that can be applied to any movable atom (mob or obj).
+ *
+ * While the atom has this component, any human mob that walks over it will have a chance to slip.
+ * Duration, tiles moved, and so on, depend on what variables are passed in when the component is added.
+ *
+ */
+/datum/component/slippery
+ /// Text that gets displayed in the slip proc, i.e. "user slips on [description]"
+ var/description
+ /// The amount of stun to apply after slip.
+ var/stun
+ /// The amount of weaken to apply after slip.
+ var/weaken
+ /// The chance that walking over the parent will slip you.
+ var/slip_chance
+ /// The amount of tiles someone will be moved after slip.
+ var/slip_tiles
+ /// TRUE If this slip can be avoided by walking.
+ var/walking_is_safe
+ /// FALSE if you want no slip shoes to make you immune to the slip
+ var/slip_always
+ /// The verb that players will see when someone slips on the parent. In the form of "You [slip_verb]ped on".
+ var/slip_verb
+
+/datum/component/slippery/Initialize(_description, _stun = 0, _weaken = 0, _slip_chance = 100, _slip_tiles = 0, _walking_is_safe = TRUE, _slip_always = FALSE, _slip_verb = "slip")
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ description = _description
+ stun = max(0, _stun)
+ weaken = max(0, _weaken)
+ slip_chance = max(0, _slip_chance)
+ slip_tiles = max(0, _slip_tiles)
+ walking_is_safe = _walking_is_safe
+ slip_always = _slip_always
+ slip_verb = _slip_verb
+
+/datum/component/slippery/RegisterWithParent()
+ RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip)
+
+/datum/component/slippery/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED))
+
+/**
+ Called whenever the parent recieves either the `MOVABLE_CROSSED` signal or the `ATOM_ENTERED` signal.
+
+ Calls the `victim`'s `slip()` proc with the component's variables as arguments.
+ Additionally calls the parent's `after_slip()` proc on the `victim`.
+*/
+/datum/component/slippery/proc/Slip(datum/source, mob/living/carbon/human/victim)
+ if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb))
+ var/atom/movable/owner = parent
+ owner.after_slip(victim)
diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm
index 818e78e8d2e..4c55ad2ad82 100644
--- a/code/datums/components/squeak.dm
+++ b/code/datums/components/squeak.dm
@@ -16,7 +16,7 @@
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak)
- if(ismovableatom(parent))
+ if(ismovable(parent))
RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak)
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed)
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
diff --git a/code/datums/components/swarming.dm b/code/datums/components/swarming.dm
new file mode 100644
index 00000000000..16ddc66280e
--- /dev/null
+++ b/code/datums/components/swarming.dm
@@ -0,0 +1,55 @@
+/datum/component/swarming
+ var/offset_x = 0
+ var/offset_y = 0
+ var/is_swarming = FALSE
+ var/list/swarm_members = list()
+
+/datum/component/swarming/Initialize(max_x = 24, max_y = 24)
+ if(!ismovable(parent))
+ return COMPONENT_INCOMPATIBLE
+ offset_x = rand(-max_x, max_x)
+ offset_y = rand(-max_y, max_y)
+
+ RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/join_swarm)
+ RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm)
+
+/datum/component/swarming/Destroy()
+ for(var/other in swarm_members)
+ var/datum/component/swarming/other_swarm = other
+ other_swarm.swarm_members -= src
+ if(!other_swarm.swarm_members.len)
+ other_swarm.unswarm()
+ swarm_members = null
+ return ..()
+
+/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM)
+ var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming)
+ if(!other_swarm)
+ return
+ swarm()
+ swarm_members |= other_swarm
+ other_swarm.swarm()
+ other_swarm.swarm_members |= src
+
+/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/AM)
+ var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming)
+ if(!other_swarm || !(other_swarm in swarm_members))
+ return
+ swarm_members -= other_swarm
+ if(!swarm_members.len)
+ unswarm()
+ other_swarm.swarm_members -= src
+ if(!other_swarm.swarm_members.len)
+ other_swarm.unswarm()
+
+/datum/component/swarming/proc/swarm()
+ var/atom/movable/owner = parent
+ if(!is_swarming)
+ is_swarming = TRUE
+ animate(owner, pixel_x = owner.pixel_x + offset_x, pixel_y = owner.pixel_y + offset_y, time = 2)
+
+/datum/component/swarming/proc/unswarm()
+ var/atom/movable/owner = parent
+ if(is_swarming)
+ animate(owner, pixel_x = owner.pixel_x - offset_x, pixel_y = owner.pixel_y - offset_y, time = 2)
+ is_swarming = FALSE
diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm
deleted file mode 100644
index a1f538e4dd7..00000000000
--- a/code/datums/components/waddling.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/component/waddling
- dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
-
-/datum/component/waddling/Initialize()
- if(!isliving(parent))
- return COMPONENT_INCOMPATIBLE
- RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
-
-/datum/component/waddling/proc/Waddle()
- var/mob/living/L = parent
- if(L.incapacitated() || L.lying)
- return
- animate(L, pixel_z = 4, time = 0)
- animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
- animate(pixel_z = 0, transform = matrix(), time = 0)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index fa8bb1db9e2..0e98179e2f9 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -1,7 +1,3 @@
-/hook/startup/proc/createDatacore()
- GLOB.data_core = new /datum/datacore()
- return 1
-
/datum/datacore
var/list/medical = list()
var/list/general = list()
@@ -624,7 +620,7 @@ GLOBAL_VAR_INIT(record_id_num, 1001)
clothes_s = new /icon('icons/mob/uniform.dmi', "syndicate_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY)
- else if(H.mind && H.mind.assigned_role in get_all_centcom_jobs())
+ else if(H.mind && (H.mind.assigned_role in get_all_centcom_jobs()))
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
else
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 00054349e36..6a183987a30 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -5,7 +5,7 @@
/// Status traits attached to this datum
var/list/status_traits
var/list/comp_lookup
- var/list/signal_procs
+ var/list/list/datum/callback/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/var_edited = FALSE //Warranty void if seal is broken
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index b2b09003934..dc6101630bf 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -1,5 +1,14 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
+/**
+ * Proc to check if a datum allows proc calls on it
+ *
+ * Returns TRUE if you can call a proc on the datum, FALSE if you cant
+ *
+ */
+/datum/proc/CanProcCall(procname)
+ return TRUE
+
/datum/proc/can_vv_get(var_name)
return TRUE
@@ -819,6 +828,59 @@
message_admins("[key_name(usr)] has made [A] process normally")
return TRUE
+ else if(href_list["modifyarmor"])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+ var/obj/A = locateUID(href_list["modifyarmor"])
+ if(!istype(A))
+ return
+ A.var_edited = TRUE
+ var/list/armorlist = A.armor.getList()
+ var/list/displaylist
+
+ var/result
+ do
+ displaylist = list()
+ for(var/key in armorlist)
+ displaylist += "[key] = [armorlist[key]]"
+ result = input(usr, "Select an armor type to modify..", "Modify armor") as null|anything in displaylist + "(ADD ALL)" + "(SET ALL)" + "(DONE)"
+
+ if(result == "(DONE)")
+ break
+ else if(result == "(ADD ALL)" || result == "(SET ALL)")
+ var/new_amount = input(usr, result == "(ADD ALL)" ? "Enter armor to add to all types:" : "Enter new armor value for all types:", "Modify all types") as num|null
+ if(isnull(new_amount))
+ continue
+ var/proper_amount = text2num(new_amount)
+ if(isnull(proper_amount))
+ continue
+ for(var/key in armorlist)
+ armorlist[key] = (result == "(ADD ALL)" ? armorlist[key] : 0) + proper_amount
+ else if(result)
+ var/list/fields = splittext(result, " = ")
+ if(length(fields) != 2)
+ continue
+ var/type = fields[1]
+ if(isnull(armorlist[type]))
+ continue
+ var/new_amount = input(usr, "Enter new armor value for [type]:", "Modify [type]") as num|null
+ if(isnull(new_amount))
+ continue
+ var/proper_amount = text2num(new_amount)
+ if(isnull(proper_amount))
+ continue
+ armorlist[type] = proper_amount
+ while(result)
+
+ if(!result || !A)
+ return TRUE
+
+ A.armor = A.armor.setRating(armorlist["melee"], armorlist["bullet"], armorlist["laser"], armorlist["energy"], armorlist["bomb"], armorlist["bio"], armorlist["rad"], armorlist["fire"], armorlist["acid"], armorlist["magic"])
+
+ log_admin("[key_name(usr)] modified the armor on [A] to: melee = [armorlist["melee"]], bullet = [armorlist["bullet"]], laser = [armorlist["laser"]], energy = [armorlist["energy"]], bomb = [armorlist["bomb"]], bio = [armorlist["bio"]], rad = [armorlist["rad"]], fire = [armorlist["fire"]], acid = [armorlist["acid"]], magic = [armorlist["magic"]]")
+ message_admins("[key_name(usr)] modified the armor on [A] to: melee = [armorlist["melee"]], bullet = [armorlist["bullet"]], laser = [armorlist["laser"]], energy = [armorlist["energy"]], bomb = [armorlist["bomb"]], bio = [armorlist["bio"]], rad = [armorlist["rad"]], fire = [armorlist["fire"]], acid = [armorlist["acid"]], magic = [armorlist["magic"]]")
+ return TRUE
+
else if(href_list["addreagent"]) /* Made on /TG/, credit to them. */
if(!check_rights(R_DEBUG|R_ADMIN)) return
@@ -1179,22 +1241,6 @@
log_admin("[key_name(usr)] has removed the organ [rem_organ] from [key_name(M)]")
qdel(rem_organ)
- else if(href_list["fix_nano"])
- if(!check_rights(R_DEBUG)) return
-
- var/mob/H = locateUID(href_list["fix_nano"])
-
- if(!istype(H) || !H.client)
- to_chat(usr, "This can only be done on mobs with clients")
- return
-
- H.client.reload_nanoui_resources()
-
- to_chat(usr, "Resource files sent")
- to_chat(H, "Your NanoUI Resource files have been refreshed")
-
- log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)]")
-
else if(href_list["regenerateicons"])
if(!check_rights(0)) return
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
index 63fa3af0605..81312cdfcc4 100644
--- a/code/datums/diseases/_MobProcs.dm
+++ b/code/datums/diseases/_MobProcs.dm
@@ -126,11 +126,19 @@
AddDisease(D)
+/**
+ * Forces the mob to contract a virus. If the mob can have viruses. Ignores clothing and other protection
+ * Returns TRUE if it succeeds. False if it doesn't
+ *
+ * Arguments:
+ * * D - the disease the mob will try to contract
+ */
//Same as ContractDisease, except never overidden clothes checks
/mob/proc/ForceContractDisease(datum/disease/D)
if(!CanContractDisease(D))
- return 0
+ return FALSE
AddDisease(D)
+ return TRUE
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 5464bd9f012..318dd176e45 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -171,7 +171,6 @@ GLOBAL_LIST_INIT(advance_cures, list(
if(!symptoms || !symptoms.len)
CRASH("We did not have any symptoms before generating properties.")
- return
var/list/properties = list("resistance" = 1, "stealth" = 0, "stage_rate" = 1, "transmittable" = 1, "severity" = 0)
@@ -196,9 +195,9 @@ GLOBAL_LIST_INIT(advance_cures, list(
visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
// The more symptoms we have, the less transmittable it is but some symptoms can make up for it.
- SetSpread(Clamp(2 ** (properties["transmittable"] - symptoms.len), BLOOD, AIRBORNE))
- permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1)
- cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20
+ SetSpread(clamp(2 ** (properties["transmittable"] - symptoms.len), BLOOD, AIRBORNE))
+ permeability_mod = max(CEILING(0.4 * properties["transmittable"], 1), 1)
+ cure_chance = 15 - clamp(properties["resistance"], -5, 5) // can be between 10 and 20
stage_prob = max(properties["stage_rate"], 2)
SetSeverity(properties["severity"])
GenerateCure(properties)
@@ -245,7 +244,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
// Will generate a random cure, the less resistance the symptoms have, the harder the cure.
/datum/disease/advance/proc/GenerateCure(list/properties = list())
if(properties && properties.len)
- var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, GLOB.advance_cures.len)
+ var/res = clamp(properties["resistance"] - (symptoms.len / 2), 1, GLOB.advance_cures.len)
// to_chat(world, "Res = [res]")
cures = list(GLOB.advance_cures[res])
@@ -396,8 +395,9 @@ GLOBAL_LIST_INIT(advance_cures, list(
for(var/datum/disease/advance/AD in GLOB.active_diseases)
AD.Refresh()
- for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list))
- if(!is_station_level(H.z))
+ for(var/thing in shuffle(GLOB.human_list))
+ var/mob/living/carbon/human/H = thing
+ if(H.stat == DEAD || !is_station_level(H.z))
continue
if(!H.HasDisease(D))
H.ForceContractDisease(D)
diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm
index 1a9bba6961e..a3111478b26 100644
--- a/code/datums/diseases/advance/symptoms/deafness.dm
+++ b/code/datums/diseases/advance/symptoms/deafness.dm
@@ -33,7 +33,7 @@ Bonus
if(3, 4)
to_chat(M, "[pick("You hear a ringing in your ear.", "Your ears pop.")]")
if(5)
- if(!(M.disabilities & DEAF))
+ if(!(DEAF in M.mutations))
to_chat(M, "Your ears pop and begin ringing loudly!")
M.BecomeDeaf()
spawn(200)
diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm
index cf39d91a866..5759ab32de6 100644
--- a/code/datums/diseases/advance/symptoms/sensory.dm
+++ b/code/datums/diseases/advance/symptoms/sensory.dm
@@ -62,4 +62,4 @@ Bonus
M.reagents.add_reagent("oculine", 20)
else
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
- to_chat(M, "[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your healing feels more acute.")]")
+ to_chat(M, "[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your hearing feels more acute.")]")
diff --git a/code/datums/diseases/advance/symptoms/skin.dm b/code/datums/diseases/advance/symptoms/skin.dm
index aa5a3494584..a3346dce800 100644
--- a/code/datums/diseases/advance/symptoms/skin.dm
+++ b/code/datums/diseases/advance/symptoms/skin.dm
@@ -35,7 +35,7 @@ BONUS
switch(A.stage)
if(5)
H.s_tone = -85
- H.update_body(0)
+ H.update_body()
else
H.visible_message("[H] looks a bit pale...", "Your skin suddenly appears lighter...")
@@ -79,7 +79,7 @@ BONUS
switch(A.stage)
if(5)
H.s_tone = 85
- H.update_body(0)
+ H.update_body()
else
H.visible_message("[H] looks a bit dark...", "Your skin suddenly appears darker...")
diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm
index cacd229c429..02f36b532d7 100644
--- a/code/datums/diseases/brainrot.dm
+++ b/code/datums/diseases/brainrot.dm
@@ -30,7 +30,7 @@
affected_mob.emote("stare")
if(prob(2))
affected_mob.emote("drool")
- if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now
+ if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't brainpain you to death now
affected_mob.adjustBrainLoss(2)
if(prob(2))
to_chat(affected_mob, "Your try to remember something important...but can't.")
@@ -40,7 +40,7 @@
affected_mob.emote("stare")
if(prob(2))
affected_mob.emote("drool")
- if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now
+ if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't brainpain you to death now
affected_mob.adjustBrainLoss(3)
if(prob(2))
to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.")
diff --git a/code/datums/diseases/critical.dm b/code/datums/diseases/critical.dm
index 8dc910e3baf..e8486a8f408 100644
--- a/code/datums/diseases/critical.dm
+++ b/code/datums/diseases/critical.dm
@@ -159,7 +159,7 @@
var/mob/living/carbon/human/H = affected_mob
if(NO_HUNGER in H.dna.species.species_traits)
return TRUE
- if(ismachine(H))
+ if(ismachineperson(H))
return TRUE
return ..()
@@ -199,4 +199,4 @@
affected_mob.emote("collapse")
if(prob(12))
to_chat(affected_mob, "You feel [pick("tired", "exhausted", "sluggish")].")
- affected_mob.Slowed(rand(4, 16))
\ No newline at end of file
+ affected_mob.Slowed(rand(4, 16))
diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm
index 158324e72f1..bb85f62199a 100644
--- a/code/datums/diseases/wizarditis.dm
+++ b/code/datums/diseases/wizarditis.dm
@@ -9,7 +9,7 @@
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
- desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
+ desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of dementia, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
severity = HARMFUL
required_organs = list(/obj/item/organ/external/head)
diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm
new file mode 100644
index 00000000000..46a295f90be
--- /dev/null
+++ b/code/datums/elements/_element.dm
@@ -0,0 +1,55 @@
+/**
+ * A holder for simple behaviour that can be attached to many different types
+ *
+ * Only one element of each type is instanced during game init.
+ * Otherwise acts basically like a lightweight component.
+ */
+/datum/element
+ /// Option flags for element behaviour
+ var/element_flags = NONE
+ /**
+ * The index of the first attach argument to consider for duplicate elements
+ *
+ * Is only used when flags contains [ELEMENT_BESPOKE]
+ *
+ * This is infinity so you must explicitly set this
+ */
+ var/id_arg_index = INFINITY
+
+/// Activates the functionality defined by the element on the given target datum
+/datum/element/proc/Attach(datum/target)
+ SHOULD_CALL_PARENT(1)
+ if(type == /datum/element)
+ return ELEMENT_INCOMPATIBLE
+ SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src)
+ if(element_flags & ELEMENT_DETACH)
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE)
+
+/// Deactivates the functionality defines by the element on the given datum
+/datum/element/proc/Detach(datum/source, force)
+ SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src)
+ SHOULD_CALL_PARENT(1)
+ UnregisterSignal(source, COMSIG_PARENT_QDELETING)
+
+/datum/element/Destroy(force)
+ if(!force)
+ return QDEL_HINT_LETMELIVE
+ SSdcs.elements_by_type -= type
+ return ..()
+
+//DATUM PROCS
+
+/// Finds the singleton for the element type given and attaches it to src
+/datum/proc/_AddElement(list/arguments)
+ var/datum/element/ele = SSdcs.GetElement(arguments)
+ arguments[1] = src
+ if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE)
+ CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]")
+
+/**
+ * Finds the singleton for the element type given and detaches it from src
+ * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE]
+ */
+/datum/proc/_RemoveElement(list/arguments)
+ var/datum/element/ele = SSdcs.GetElement(arguments)
+ ele.Detach(src)
diff --git a/code/datums/elements/waddling.dm b/code/datums/elements/waddling.dm
new file mode 100644
index 00000000000..e8870653941
--- /dev/null
+++ b/code/datums/elements/waddling.dm
@@ -0,0 +1,25 @@
+/datum/element/waddling
+
+/datum/element/waddling/Attach(datum/target)
+ . = ..()
+ if(!ismovable(target))
+ return ELEMENT_INCOMPATIBLE
+ if(isliving(target))
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/LivingWaddle)
+ else
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Waddle)
+
+/datum/element/waddling/Detach(datum/source, force)
+ . = ..()
+ UnregisterSignal(source, COMSIG_MOVABLE_MOVED)
+
+/datum/element/waddling/proc/LivingWaddle(mob/living/target)
+ if(target.incapacitated() || target.lying)
+ return
+ Waddle(target)
+
+/datum/element/waddling/proc/Waddle(atom/movable/target)
+ animate(target, pixel_z = 4, time = 0)
+ var/prev_trans = matrix(target.transform)
+ animate(pixel_z = 0, transform = turn(target.transform, pick(-12, 0, 12)), time = 2)
+ animate(pixel_z = 0, transform = prev_trans, time = 0)
diff --git a/code/datums/gas_mixture.dm b/code/datums/gas_mixture.dm
index 35cc970aa67..91bebcdad39 100644
--- a/code/datums/gas_mixture.dm
+++ b/code/datums/gas_mixture.dm
@@ -7,33 +7,22 @@ What are the archived variables for?
#define SPECIFIC_HEAT_TOXIN 200
#define SPECIFIC_HEAT_AIR 20
#define SPECIFIC_HEAT_CDO 30
-#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \
- (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN)
+#define SPECIFIC_HEAT_N2O 40
+#define SPECIFIC_HEAT_AGENT_B 300
+
+#define HEAT_CAPACITY_CALCULATION(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b) \
+ (carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + toxins * SPECIFIC_HEAT_TOXIN + sleeping_agent * SPECIFIC_HEAT_N2O + agent_b * SPECIFIC_HEAT_AGENT_B)
#define MINIMUM_HEAT_CAPACITY 0.0003
-#define QUANTIZE(variable) (round(variable,0.0001))
-
-/datum/gas
- var/moles = 0
- var/specific_heat = 0
-
- var/moles_archived = 0
-
-/datum/gas/sleeping_agent
- specific_heat = 40
-
-/datum/gas/oxygen_agent_b
- specific_heat = 300
-
-/datum/gas/volatile_fuel
- specific_heat = 30
-
+#define QUANTIZE(variable) (round(variable, 0.0001))
/datum/gas_mixture
var/oxygen = 0
var/carbon_dioxide = 0
var/nitrogen = 0
var/toxins = 0
+ var/sleeping_agent = 0
+ var/agent_b = 0
var/volume = CELL_VOLUME
@@ -41,13 +30,12 @@ What are the archived variables for?
var/last_share
- var/list/datum/gas/trace_gases = list()
-
-
var/tmp/oxygen_archived
var/tmp/carbon_dioxide_archived
var/tmp/nitrogen_archived
var/tmp/toxins_archived
+ var/tmp/sleeping_agent_archived
+ var/tmp/agent_b_archived
var/tmp/temperature_archived
@@ -55,35 +43,24 @@ What are the archived variables for?
//PV=nRT - related procedures
/datum/gas_mixture/proc/heat_capacity()
- var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins)
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- heat_capacity += trace_gas.moles*trace_gas.specific_heat
- return heat_capacity
+ return HEAT_CAPACITY_CALCULATION(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b)
/datum/gas_mixture/proc/heat_capacity_archived()
- var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived)
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat
- return heat_capacity_archived
+ return HEAT_CAPACITY_CALCULATION(oxygen_archived, carbon_dioxide_archived, nitrogen_archived, toxins_archived, sleeping_agent_archived, agent_b_archived)
/datum/gas_mixture/proc/total_moles()
- var/moles = oxygen + carbon_dioxide + nitrogen + toxins
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- moles += trace_gas.moles
+ var/moles = oxygen + carbon_dioxide + nitrogen + toxins + sleeping_agent + agent_b
return moles
+/datum/gas_mixture/proc/total_trace_moles()
+ var/moles = sleeping_agent + agent_b
+ return moles
/datum/gas_mixture/proc/return_pressure()
- if(volume>0)
- return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
+ if(volume > 0)
+ return total_moles() * R_IDEAL_GAS_EQUATION * temperature / volume
return 0
@@ -96,7 +73,7 @@ What are the archived variables for?
/datum/gas_mixture/proc/thermal_energy()
- return temperature*heat_capacity()
+ return temperature * heat_capacity()
//Procedures used for very specific events
@@ -105,28 +82,23 @@ What are the archived variables for?
/datum/gas_mixture/proc/react(atom/dump_location)
var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
- if(trace_gases.len > 0)
- if(temperature > 900)
- if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY)
- var/datum/gas/oxygen_agent_b/trace_gas = locate(/datum/gas/oxygen_agent_b/) in trace_gases
- if(trace_gas)
- var/reaction_rate = min(carbon_dioxide*0.75, toxins*0.25, trace_gas.moles*0.05)
+ if(agent_b && temperature > 900)
+ if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY)
+ var/reaction_rate = min(carbon_dioxide * 0.75, toxins * 0.25, agent_b * 0.05)
- carbon_dioxide -= reaction_rate
- oxygen += reaction_rate
+ carbon_dioxide -= reaction_rate
+ oxygen += reaction_rate
- trace_gas.moles -= reaction_rate*0.05
+ agent_b -= reaction_rate * 0.05
- temperature += (reaction_rate*20000)/heat_capacity()
+ temperature += (reaction_rate * 20000) / heat_capacity()
- reacting = 1
+ reacting = 1
fuel_burnt = 0
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
-// to_chat(world, "pre [temperature], [oxygen], [toxins]")
if(fire() > 0)
reacting = 1
-// to_chat(world, "post [temperature], [oxygen], [toxins]")
return reacting
@@ -134,24 +106,6 @@ What are the archived variables for?
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
- var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel/) in trace_gases
- if(fuel_store) //General volatile gas burn
- var/burned_fuel = 0
-
- if(oxygen < fuel_store.moles)
- burned_fuel = oxygen
- fuel_store.moles -= burned_fuel
- oxygen = 0
- else
- burned_fuel = fuel_store.moles
- oxygen -= fuel_store.moles
- trace_gases -= fuel_store
- fuel_store = null
-
- energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
- carbon_dioxide += burned_fuel
- fuel_burnt += burned_fuel
-
//Handle plasma burning
if(toxins > MINIMUM_HEAT_CAPACITY)
var/plasma_burn_rate = 0
@@ -161,13 +115,13 @@ What are the archived variables for?
if(temperature > PLASMA_UPPER_TEMPERATURE)
temperature_scale = 1
else
- temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
+ temperature_scale = (temperature - PLASMA_MINIMUM_BURN_TEMPERATURE) / (PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
- if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN)
- plasma_burn_rate = (toxins*temperature_scale)/PLASMA_BURN_RATE_DELTA
+ if(oxygen > toxins * PLASMA_OXYGEN_FULLBURN)
+ plasma_burn_rate = (toxins * temperature_scale) / PLASMA_BURN_RATE_DELTA
else
- plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
+ plasma_burn_rate = (temperature_scale * (oxygen / PLASMA_OXYGEN_FULLBURN)) / PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
toxins -= plasma_burn_rate
oxygen -= plasma_burn_rate*oxygen_burn_rate
@@ -175,12 +129,12 @@ What are the archived variables for?
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
- fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate)
+ fuel_burnt += (plasma_burn_rate) * (1 + oxygen_burn_rate)
if(energy_released > 0)
var/new_heat_capacity = heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
+ temperature = (temperature * old_heat_capacity + energy_released) / new_heat_capacity
return fuel_burnt
@@ -231,10 +185,8 @@ What are the archived variables for?
carbon_dioxide_archived = carbon_dioxide
nitrogen_archived = nitrogen
toxins_archived = toxins
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- trace_gas.moles_archived = trace_gas.moles
+ sleeping_agent_archived = sleeping_agent
+ agent_b_archived = agent_b
temperature_archived = temperature
@@ -244,55 +196,45 @@ What are the archived variables for?
if(!giver)
return 0
- if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0)
- temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
+ temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
oxygen += giver.oxygen
carbon_dioxide += giver.carbon_dioxide
nitrogen += giver.nitrogen
toxins += giver.toxins
-
- for(var/gas in giver.trace_gases)
- var/datum/gas/trace_gas = gas
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- trace_gases += corresponding
- corresponding.moles += trace_gas.moles
+ sleeping_agent += giver.sleeping_agent
+ agent_b += giver.agent_b
return 1
/datum/gas_mixture/remove(amount)
var/sum = total_moles()
- amount = min(amount,sum) //Can not take more air than tile has!
+ amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
- removed.oxygen = QUANTIZE((oxygen/sum)*amount)
- removed.nitrogen = QUANTIZE((nitrogen/sum)*amount)
- removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount)
- removed.toxins = QUANTIZE((toxins/sum)*amount)
+ removed.oxygen = QUANTIZE((oxygen / sum) * amount)
+ removed.nitrogen = QUANTIZE((nitrogen/ sum) * amount)
+ removed.carbon_dioxide = QUANTIZE((carbon_dioxide / sum) * amount)
+ removed.toxins = QUANTIZE((toxins / sum) * amount)
+ removed.sleeping_agent = QUANTIZE((sleeping_agent / sum) * amount)
+ removed.agent_b = QUANTIZE((agent_b / sum) * amount)
oxygen -= removed.oxygen
nitrogen -= removed.nitrogen
carbon_dioxide -= removed.carbon_dioxide
toxins -= removed.toxins
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- var/datum/gas/corresponding = new trace_gas.type()
- removed.trace_gases += corresponding
-
- corresponding.moles = (trace_gas.moles/sum)*amount
- trace_gas.moles -= corresponding.moles
+ sleeping_agent -= removed.sleeping_agent
+ agent_b -= removed.agent_b
removed.temperature = temperature
@@ -307,23 +249,19 @@ What are the archived variables for?
var/datum/gas_mixture/removed = new
- removed.oxygen = QUANTIZE(oxygen*ratio)
- removed.nitrogen = QUANTIZE(nitrogen*ratio)
- removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio)
- removed.toxins = QUANTIZE(toxins*ratio)
+ removed.oxygen = QUANTIZE(oxygen * ratio)
+ removed.nitrogen = QUANTIZE(nitrogen * ratio)
+ removed.carbon_dioxide = QUANTIZE(carbon_dioxide * ratio)
+ removed.toxins = QUANTIZE(toxins * ratio)
+ removed.sleeping_agent = QUANTIZE(sleeping_agent * ratio)
+ removed.agent_b = QUANTIZE(agent_b * ratio)
oxygen -= removed.oxygen
nitrogen -= removed.nitrogen
carbon_dioxide -= removed.carbon_dioxide
toxins -= removed.toxins
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- var/datum/gas/corresponding = new trace_gas.type()
- removed.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*ratio
- trace_gas.moles -= corresponding.moles
+ sleeping_agent -= removed.sleeping_agent
+ agent_b -= removed.agent_b
removed.temperature = temperature
@@ -334,14 +272,8 @@ What are the archived variables for?
carbon_dioxide = sample.carbon_dioxide
nitrogen = sample.nitrogen
toxins = sample.toxins
-
- trace_gases.len=null
- for(var/gas in sample.trace_gases)
- var/datum/gas/trace_gas = gas
- var/datum/gas/corresponding = new trace_gas.type()
- trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles
+ sleeping_agent = sample.sleeping_agent
+ agent_b = sample.agent_b
temperature = sample.temperature
@@ -352,6 +284,8 @@ What are the archived variables for?
carbon_dioxide = model.carbon_dioxide
nitrogen = model.nitrogen
toxins = model.toxins
+ sleeping_agent = model.sleeping_agent
+ agent_b = model.agent_b
//acounts for changes in temperature
var/turf/model_parent = model.parent_type
@@ -361,26 +295,25 @@ What are the archived variables for?
return 1
/datum/gas_mixture/check_turf(turf/model, atmos_adjacent_turfs = 4)
- var/delta_oxygen = (oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
- var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
- var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/(atmos_adjacent_turfs+1)
- var/delta_toxins = (toxins_archived - model.toxins)/(atmos_adjacent_turfs+1)
+ var/delta_oxygen = (oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
+ var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
+ var/delta_nitrogen = (nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
+ var/delta_toxins = (toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
+ var/delta_sleeping_agent = (sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
+ var/delta_agent_b = (agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - model.temperature)
- if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= sleeping_agent_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= agent_b_archived * MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
- return 0
-
return 1
/datum/gas_mixture/proc/check_turf_total(turf/model) //I want this proc to die a painful death
@@ -388,30 +321,32 @@ What are the archived variables for?
var/delta_carbon_dioxide = (carbon_dioxide - model.carbon_dioxide)
var/delta_nitrogen = (nitrogen - model.nitrogen)
var/delta_toxins = (toxins - model.toxins)
+ var/delta_sleeping_agent = (sleeping_agent - model.sleeping_agent)
+ var/delta_agent_b = (agent_b - model.agent_b)
var/delta_temperature = (temperature - model.temperature)
- if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_sleeping_agent) >= sleeping_agent * MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_agent_b) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_agent_b) >= agent_b * MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND*4)
- return 0
-
return 1
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
- if(!sharer) return 0
- var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/(atmos_adjacent_turfs+1)
- var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/(atmos_adjacent_turfs+1)
- var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/(atmos_adjacent_turfs+1)
- var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/(atmos_adjacent_turfs+1)
+ if(!sharer)
+ return 0
+ var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived) / (atmos_adjacent_turfs + 1)
+ var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) / (atmos_adjacent_turfs + 1)
+ var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) / (atmos_adjacent_turfs + 1)
+ var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived) / (atmos_adjacent_turfs + 1)
+ var/delta_sleeping_agent = QUANTIZE(sleeping_agent_archived - sharer.sleeping_agent_archived) / (atmos_adjacent_turfs + 1)
+ var/delta_agent_b = QUANTIZE(agent_b_archived - sharer.agent_b_archived) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
@@ -423,28 +358,42 @@ What are the archived variables for?
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/delta_air = delta_oxygen+delta_nitrogen
+ var/delta_air = delta_oxygen + delta_nitrogen
if(delta_air)
- var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
+ var/air_heat_capacity = SPECIFIC_HEAT_AIR * delta_air
if(delta_air > 0)
heat_capacity_self_to_sharer += air_heat_capacity
else
heat_capacity_sharer_to_self -= air_heat_capacity
if(delta_carbon_dioxide)
- var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
+ var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO * delta_carbon_dioxide
if(delta_carbon_dioxide > 0)
heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
else
heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
if(delta_toxins)
- var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
+ var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN * delta_toxins
if(delta_toxins > 0)
heat_capacity_self_to_sharer += toxins_heat_capacity
else
heat_capacity_sharer_to_self -= toxins_heat_capacity
+ if(delta_sleeping_agent)
+ var/sleeping_agent_heat_capacity = SPECIFIC_HEAT_N2O * delta_sleeping_agent
+ if(delta_sleeping_agent > 0)
+ heat_capacity_self_to_sharer += sleeping_agent_heat_capacity
+ else
+ heat_capacity_sharer_to_self -= sleeping_agent_heat_capacity
+
+ if(delta_agent_b)
+ var/agent_b_heat_capacity = SPECIFIC_HEAT_AGENT_B * delta_agent_b
+ if(delta_agent_b > 0)
+ heat_capacity_self_to_sharer += agent_b_heat_capacity
+ else
+ heat_capacity_sharer_to_self -= agent_b_heat_capacity
+
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
@@ -460,83 +409,40 @@ What are the archived variables for?
toxins -= delta_toxins
sharer.toxins += delta_toxins
- var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
- last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins)
+ sleeping_agent -= delta_sleeping_agent
+ sharer.sleeping_agent += delta_sleeping_agent
- var/list/trace_types_considered = list()
+ agent_b -= delta_agent_b
+ sharer.agent_b += delta_agent_b
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
- var/delta = 0
-
- if(corresponding)
- delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/(atmos_adjacent_turfs+1)
- else
- corresponding = new trace_gas.type()
- sharer.trace_gases += corresponding
-
- delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1)
-
- trace_gas.moles -= delta
- corresponding.moles += delta
-
- if(delta)
- var/individual_heat_capacity = trace_gas.specific_heat*delta
- if(delta > 0)
- heat_capacity_self_to_sharer += individual_heat_capacity
- else
- heat_capacity_sharer_to_self -= individual_heat_capacity
-
- moved_moles += delta
- last_share += abs(delta)
-
- trace_types_considered += trace_gas.type
-
- for(var/gas in sharer.trace_gases)
- var/datum/gas/trace_gas = gas
- if(trace_gas.type in trace_types_considered)
- continue
- var/datum/gas/corresponding
- var/delta = 0
- corresponding = new trace_gas.type()
- trace_gases += corresponding
-
- delta = trace_gas.moles_archived/5
-
- trace_gas.moles -= delta
- corresponding.moles += delta
-
- //Guaranteed transfer from sharer to self
- var/individual_heat_capacity = trace_gas.specific_heat*delta
- heat_capacity_sharer_to_self += individual_heat_capacity
-
- moved_moles += -delta
- last_share += abs(delta)
+ var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins + delta_sleeping_agent + delta_agent_b)
+ last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + abs(delta_sleeping_agent) + abs(delta_agent_b)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
+ temperature = (old_self_heat_capacity * temperature - heat_capacity_self_to_sharer * temperature_archived + heat_capacity_sharer_to_self * sharer.temperature_archived) / new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
- sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
+ sharer.temperature = (old_sharer_heat_capacity * sharer.temperature - heat_capacity_sharer_to_self * sharer.temperature_archived + heat_capacity_self_to_sharer * temperature_archived) / new_sharer_heat_capacity
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
- if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
+ if(abs(new_sharer_heat_capacity / old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
- var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
- return delta_pressure*R_IDEAL_GAS_EQUATION/volume
+ var/delta_pressure = temperature_archived * (total_moles() + moved_moles) - sharer.temperature_archived * (sharer.total_moles() - moved_moles)
+ return delta_pressure * R_IDEAL_GAS_EQUATION / volume
/datum/gas_mixture/mimic(turf/model, atmos_adjacent_turfs = 4)
- var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
- var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
- var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/(atmos_adjacent_turfs+1)
- var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/(atmos_adjacent_turfs+1)
+ var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen) / (atmos_adjacent_turfs + 1)
+ var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide) / (atmos_adjacent_turfs + 1)
+ var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen) / (atmos_adjacent_turfs + 1)
+ var/delta_toxins = QUANTIZE(toxins_archived - model.toxins) / (atmos_adjacent_turfs + 1)
+ var/delta_sleeping_agent = QUANTIZE(sleeping_agent_archived - model.sleeping_agent) / (atmos_adjacent_turfs + 1)
+ var/delta_agent_b = QUANTIZE(agent_b_archived - model.agent_b) / (atmos_adjacent_turfs + 1)
var/delta_temperature = (temperature_archived - model.temperature)
@@ -546,57 +452,54 @@ What are the archived variables for?
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/delta_air = delta_oxygen+delta_nitrogen
+ var/delta_air = delta_oxygen + delta_nitrogen
if(delta_air)
- var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
- heat_transferred -= air_heat_capacity*model.temperature
+ var/air_heat_capacity = SPECIFIC_HEAT_AIR * delta_air
+ heat_transferred -= air_heat_capacity * model.temperature
heat_capacity_transferred -= air_heat_capacity
if(delta_carbon_dioxide)
- var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
- heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
+ var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO * delta_carbon_dioxide
+ heat_transferred -= carbon_dioxide_heat_capacity * model.temperature
heat_capacity_transferred -= carbon_dioxide_heat_capacity
if(delta_toxins)
- var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
- heat_transferred -= toxins_heat_capacity*model.temperature
+ var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN * delta_toxins
+ heat_transferred -= toxins_heat_capacity * model.temperature
heat_capacity_transferred -= toxins_heat_capacity
+ if(delta_sleeping_agent)
+ var/sleeping_agent_heat_capacity = SPECIFIC_HEAT_N2O * delta_sleeping_agent
+ heat_transferred -= sleeping_agent_heat_capacity * model.temperature
+ heat_capacity_transferred -= sleeping_agent_heat_capacity
+
+ if(delta_agent_b)
+ var/agent_b_heat_capacity = SPECIFIC_HEAT_AGENT_B * delta_agent_b
+ heat_transferred -= agent_b_heat_capacity * model.temperature
+ heat_capacity_transferred -= agent_b_heat_capacity
+
old_self_heat_capacity = heat_capacity()
oxygen -= delta_oxygen
carbon_dioxide -= delta_carbon_dioxide
nitrogen -= delta_nitrogen
toxins -= delta_toxins
+ sleeping_agent -= delta_sleeping_agent
+ agent_b -= delta_agent_b
- var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
- last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins)
-
- if(trace_gases.len)
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- var/delta = 0
-
- delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1)
-
- trace_gas.moles -= delta
-
- var/heat_cap_transferred = delta*trace_gas.specific_heat
- heat_transferred += heat_cap_transferred*temperature_archived
- heat_capacity_transferred += heat_cap_transferred
- moved_moles += delta
- moved_moles += abs(delta)
+ var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins + delta_sleeping_agent + delta_agent_b)
+ last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins) + abs(delta_sleeping_agent) + abs(delta_agent_b)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*temperature_archived)/new_self_heat_capacity
+ temperature = (old_self_heat_capacity * temperature - heat_capacity_transferred * temperature_archived) / new_self_heat_capacity
temperature_mimic(model, model.thermal_conductivity)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
- var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
- return delta_pressure*R_IDEAL_GAS_EQUATION/volume
+ var/delta_pressure = temperature_archived * (total_moles() + moved_moles) - model.temperature * (model.oxygen + model.carbon_dioxide + model.nitrogen + model.toxins + model.sleeping_agent + model.agent_b)
+ return delta_pressure * R_IDEAL_GAS_EQUATION / volume
else
return 0
@@ -608,11 +511,11 @@ What are the archived variables for?
var/sharer_heat_capacity = sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
+ var/heat = conduction_coefficient*delta_temperature * \
+ (self_heat_capacity * sharer_heat_capacity / (self_heat_capacity + sharer_heat_capacity))
- temperature -= heat/self_heat_capacity
- sharer.temperature += heat/sharer_heat_capacity
+ temperature -= heat / self_heat_capacity
+ sharer.temperature += heat / sharer_heat_capacity
/datum/gas_mixture/temperature_mimic(turf/model, conduction_coefficient)
var/delta_temperature = (temperature - model.temperature)
@@ -620,10 +523,10 @@ What are the archived variables for?
var/self_heat_capacity = heat_capacity()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
+ var/heat = conduction_coefficient * delta_temperature * \
+ (self_heat_capacity * model.heat_capacity / (self_heat_capacity + model.heat_capacity))
- temperature -= heat/self_heat_capacity
+ temperature -= heat / self_heat_capacity
/datum/gas_mixture/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
@@ -631,52 +534,36 @@ What are the archived variables for?
var/self_heat_capacity = heat_capacity()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
+ var/heat = conduction_coefficient * delta_temperature * \
+ (self_heat_capacity * sharer.heat_capacity / (self_heat_capacity + sharer.heat_capacity))
- temperature -= heat/self_heat_capacity
- sharer.temperature += heat/sharer.heat_capacity
+ temperature -= heat / self_heat_capacity
+ sharer.temperature += heat / sharer.heat_capacity
/datum/gas_mixture/compare(datum/gas_mixture/sample)
- if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
- ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
+ if((abs(oxygen - sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((oxygen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.oxygen) || (oxygen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.oxygen)))
return 0
- if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
- ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
+ if((abs(nitrogen - sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((nitrogen < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.nitrogen) || (nitrogen > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.nitrogen)))
return 0
- if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
- ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
+ if((abs(carbon_dioxide - sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((carbon_dioxide < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.carbon_dioxide) || (carbon_dioxide > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.carbon_dioxide)))
return 0
- if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
- ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
+ if((abs(toxins - sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((toxins < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.toxins) || (toxins > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.toxins)))
+ return 0
+ if((abs(sleeping_agent - sample.sleeping_agent) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((sleeping_agent < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.sleeping_agent) || (sleeping_agent > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.sleeping_agent)))
+ return 0
+ if((abs(agent_b - sample.agent_b) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((agent_b < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.agent_b) || (agent_b > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.agent_b)))
return 0
if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
- if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
- ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
+ if((abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
+ ((temperature < (1 - MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.temperature) || (temperature > (1 + MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND) * sample.temperature)))
return 0
-
- for(var/gas in sample.trace_gases)
- var/datum/gas/trace_gas = gas
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if(corresponding)
- if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
- ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
- return 0
- else
- return 0
-
- for(var/gas in trace_gases)
- var/datum/gas/trace_gas = gas
- if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
- var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases
- if(corresponding)
- if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
- ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
- return 0
- else
- return 0
return 1
@@ -691,12 +578,12 @@ What are the archived variables for?
//Does handle trace gases!
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
- return (gas_pressure*R_IDEAL_GAS_EQUATION*temperature)/BREATH_VOLUME
+ return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
//Reverse of the above
/datum/gas_mixture/proc/get_true_breath_pressure(breath_pp)
- return (breath_pp*BREATH_VOLUME)/(R_IDEAL_GAS_EQUATION*temperature)
+ return (breath_pp * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
//Mathematical proofs:
/*
diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm
index c10ca5a488b..8eefe5efa0d 100644
--- a/code/datums/helper_datums/construction_datum.dm
+++ b/code/datums/helper_datums/construction_datum.dm
@@ -69,10 +69,10 @@
/datum/construction/proc/check_all_steps(atom/used_atom,mob/user as mob) //check all steps, remove matching one.
for(var/i=1;i<=steps.len;i++)
- var/list/L = steps[i];
+ var/list/L = steps[i]
if(do_tool_or_atom_check(used_atom, L["key"]) && custom_action(i, used_atom, user))
steps[i]=null;//stupid byond list from list removal...
- listclearnulls(steps);
+ listclearnulls(steps)
if(!steps.len)
spawn_result(user)
return 1
diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm
deleted file mode 100644
index 214045941b5..00000000000
--- a/code/datums/helper_datums/global_iterator.dm
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-README:
-
-The global_iterator datum is supposed to provide a simple and robust way to
-create some constantly "looping" processes with ability to stop and restart them at will.
-Generally, the only thing you want to play with (meaning, redefine) is the process() proc.
-It must contain all the things you want done.
-
-Control functions:
- new - used to create datum. First argument (optional) - var list(to use in process() proc) as list,
- second (optional) - autostart control.
- If autostart == TRUE, the loop will be started immediately after datum creation.
-
- start(list/arguments) - starts the loop. Takes arguments(optional) as a list, which is then used
- by process() proc. Returns null if datum already active, 1 if loop started succesfully and 0 if there's
- an error in supplied arguments (not list or empty list).
-
- stop() - stops the loop. Returns null if datum is already inactive and 1 on success.
-
- set_delay(new_delay) - sets the delay between iterations. Pretty selfexplanatory.
- Returns 0 on error(new_delay is not numerical), 1 otherwise.
-
- set_process_args(list/arguments) - passes the supplied arguments to the process() proc.
-
- active() - Returns 1 if datum is active, 0 otherwise.
-
- toggle() - toggles datum state. Returns new datum state (see active()).
-
-Misc functions:
-
- get_last_exec_time() - Returns the time of last iteration.
-
- get_last_exec_time_as_text() - Returns the time of last iteration as text
-
-
-Control vars:
-
- delay - delay between iterations
-
- check_for_null - if equals TRUE, on each iteration the supplied arguments will be checked for nulls.
- If some varible equals null (and null only), the loop is stopped.
- Usefull, if some var unexpectedly becomes null - due to object deletion, for example.
- Of course, you can also check the variables inside process() proc to prevent runtime errors.
-
-Data storage vars:
-
- result - stores the value returned by process() proc
-*/
-
-/datum/global_iterator
- var/control_switch = 0
- var/delay = 10
- var/list/arg_list = new
- var/last_exec = null
- var/check_for_null = 1
- var/forbid_garbage = 0
- var/result
- var/state = 0
-
-/datum/global_iterator/New(list/arguments=null,autostart=1)
- delay = delay>0?(delay):1
- if(forbid_garbage) //prevents garbage collection with tag != null
- tag = "\ref[src]"
- set_process_args(arguments)
- if(autostart)
- start()
- return
-
-/datum/global_iterator/proc/main()
- state = 1
- while(src && control_switch)
- last_exec = world.timeofday
- if(check_for_null && has_null_args())
- stop()
- return 0
- result = process(arglist(arg_list))
- for(var/sleep_time=delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace.
- if(!control_switch)
- return 0
- sleep(1)
- return 0
-
-/datum/global_iterator/proc/start(list/arguments=null)
- if(active())
- return
- if(arguments)
- if(!set_process_args(arguments))
- return 0
- if(!state_check()) //the main loop is sleeping, wait for it to terminate.
- return
- control_switch = 1
- spawn()
- state = main()
- return 1
-
-/datum/global_iterator/proc/stop()
- if(!active())
- return
- control_switch = 0
- spawn(-1) //report termination error but don't wait for state_check().
- state_check()
- return 1
-
-/datum/global_iterator/proc/state_check()
- var/lag = 0
- while(state)
- sleep(1)
- if(++lag>10)
- CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.")
- return 1
-
-/datum/global_iterator/process()
- return
-
-/datum/global_iterator/proc/active()
- return control_switch
-
-/datum/global_iterator/proc/has_null_args()
- if(null in arg_list)
- return 1
- return 0
-
-
-/datum/global_iterator/proc/set_delay(new_delay)
- if(isnum(new_delay))
- delay = max(1, round(new_delay))
- return 1
- else
- return 0
-
-/datum/global_iterator/proc/get_last_exec_time()
- return (last_exec||0)
-
-/datum/global_iterator/proc/get_last_exec_time_as_text()
- return (time2text(last_exec)||"Wasn't executed yet")
-
-/datum/global_iterator/proc/set_process_args(list/arguments)
- if(arguments && istype(arguments, /list) && arguments.len)
- arg_list = arguments
- return 1
- else
-// to_chat(world, "Invalid arguments supplied for [src.type], ref = \ref[src]")
- return 0
-
-/datum/global_iterator/proc/toggle_null_checks()
- check_for_null = !check_for_null
- return check_for_null
-
-/datum/global_iterator/proc/toggle()
- if(!stop())
- start()
- return active()
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
index a54707842db..ee5a4df4f5b 100644
--- a/code/datums/helper_datums/map_template.dm
+++ b/code/datums/helper_datums/map_template.dm
@@ -17,7 +17,7 @@
name = rename
/datum/map_template/proc/preload_size(path)
- var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1)
+ var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, shouldCropMap = FALSE, measureOnly = TRUE)
if(bounds)
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
height = bounds[MAP_MAXY]
@@ -49,7 +49,7 @@
// if given a multi-z template
// it might need to be adapted for that when that time comes
GLOB.space_manager.add_dirt(placement.z)
- var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1)
+ var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE)
if(!bounds)
return 0
if(bot_left == null || top_right == null)
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index 9bba49f2678..4e20d2a675e 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -211,7 +211,7 @@
var/datum/gas_mixture/A = F.air
// Can most things breathe?
- if(A.trace_gases.len)
+ if(A.sleeping_agent)
continue
if(A.oxygen < 16)
continue
diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm
index b8684072c3f..369c01cce42 100644
--- a/code/datums/holocall.dm
+++ b/code/datums/holocall.dm
@@ -148,7 +148,6 @@
eye.eye_user = user
eye.name = "Camera Eye ([user.name])"
user.remote_control = eye
- user.remote_view = 1
user.reset_perspective(eye)
eye.setLoc(get_turf(H))
diff --git a/code/datums/log_viewer.dm b/code/datums/log_viewer.dm
index 53d330b391d..5f7084a738b 100644
--- a/code/datums/log_viewer.dm
+++ b/code/datums/log_viewer.dm
@@ -137,6 +137,9 @@ if(!result || result.ckey != __ckey){\
dat += "Mobs being used:"
for(var/i in selected_mobs)
var/mob/M = i
+ if(QDELETED(M))
+ selected_mobs -= i
+ continue
dat += "[get_display_name(M)]"
dat += "Add Mob"
dat += "Clear All Mobs"
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 4f176970a92..0c992bbb32c 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -39,7 +39,6 @@
var/role_alt_title
var/datum/job/assigned_job
- var/list/kills = list()
var/list/datum/objective/objectives = list()
var/list/datum/objective/special_verbs = list()
var/list/targets = list()
@@ -48,30 +47,23 @@
var/miming = 0 // Mime's vow of silence
var/list/antag_datums
- var/speech_span // What span any body this mind has talks in.
- var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
var/linglink
var/datum/vampire/vampire //vampire holder
var/datum/abductor/abductor //abductor holder
- var/datum/devilinfo/devilinfo //devil holder
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD
var/datum/mindslaves/som //stands for slave or master...hush..
var/datum/devilinfo/devilinfo //Information about the devil, if any.
- var/damnation_type = 0
- var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src
+ var/damnation_type = 0
+ var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src
var/hasSoul = TRUE
- var/rev_cooldown = 0
-
var/isholy = FALSE // is this person a chaplain or admin role allowed to use bibles
var/isblessed = FALSE // is this person blessed by a chaplain?
var/num_blessed = 0 // for prayers
- // the world.time since the mob has been brigged, or -1 if not at all
- var/brigged_since = -1
var/suicided = FALSE
//put this here for easier tracking ingame
@@ -94,6 +86,9 @@
if(antag_datum.delete_on_mind_deletion)
qdel(i)
antag_datums = null
+ current = null
+ original = null
+ soulOwner = null
return ..()
/datum/mind/proc/transfer_to(mob/living/new_character)
@@ -539,13 +534,22 @@
var/mob/def_target = null
var/objective_list[] = list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain)
if(objective&&(objective.type in objective_list) && objective:target)
- def_target = objective:target.current
+ def_target = objective.target.current
possible_targets = sortAtom(possible_targets)
- possible_targets += "Free objective"
- var/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
- if(!new_target)
- return
+ var/new_target
+ if(length(possible_targets) > 0)
+ if(alert(usr, "Do you want to pick the objective yourself? No will randomise it", "Pick objective", "Yes", "No") == "Yes")
+ possible_targets += "Free objective"
+ new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
+ else
+ new_target = pick(possible_targets)
+
+ if(!new_target)
+ return
+ else
+ to_chat(usr, "No possible target found. Defaulting to a Free objective.")
+ new_target = "Free objective"
var/objective_path = text2path("/datum/objective/[new_obj_type]")
if(new_target == "Free objective")
@@ -1407,9 +1411,10 @@
return A
/datum/mind/proc/announce_objectives()
- to_chat(current, "Your current objectives:")
- for(var/line in splittext(gen_objective_text(), " "))
- to_chat(current, line)
+ if(current)
+ to_chat(current, "Your current objectives:")
+ for(var/line in splittext(gen_objective_text(), " "))
+ to_chat(current, line)
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
@@ -1578,25 +1583,6 @@
L = agent_landmarks[team]
H.forceMove(L.loc)
-
-// check whether this mind's mob has been brigged for the given duration
-// have to call this periodically for the duration to work properly
-/datum/mind/proc/is_brigged(duration)
- var/turf/T = current.loc
- if(!istype(T))
- brigged_since = -1
- return 0
-
- var/is_currently_brigged = current.is_in_brig()
- if(!is_currently_brigged)
- brigged_since = -1
- return 0
-
- if(brigged_since == -1)
- brigged_since = world.time
-
- return (duration <= world.time - brigged_since)
-
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
spell_list += S
S.action.Grant(current)
@@ -1684,7 +1670,7 @@
if(H.w_uniform)
jumpsuit = H.w_uniform
jumpsuit.color = team_color
- H.update_inv_w_uniform(0,0)
+ H.update_inv_w_uniform()
add_attack_logs(missionary, current, "Converted to a zealot for [convert_duration/600] minutes")
addtimer(CALLBACK(src, .proc/remove_zealot, jumpsuit), convert_duration) //deconverts after the timer expires
@@ -1701,7 +1687,7 @@
jumpsuit.color = initial(jumpsuit.color) //reset the jumpsuit no matter where our mind is
if(ishuman(current)) //but only try updating us if we are still a human type since it is a human proc
var/mob/living/carbon/human/H = current
- H.update_inv_w_uniform(0,0)
+ H.update_inv_w_uniform()
to_chat(current, "You seem to have forgotten the events of the past 10 minutes or so, and your head aches a bit as if someone beat it savagely with a stick.")
to_chat(current, "This means you don't remember who you were working for or what you were doing.")
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index 0887290a6f4..4d870e1296c 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -22,5 +22,4 @@
/mutable_appearance/clean/New()
. = ..()
alpha = 255
- opacity = 1
transform = null
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index db5cca6e9ec..416c4f9c02d 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -1,5 +1,5 @@
/datum/outfit
- var/name = "Naked"
+ var/name = "SOMEBODY FORGOT TO SET A NAME, NOTIFY A CODER"
var/collect_not_del = FALSE
var/uniform = null
@@ -33,6 +33,9 @@
var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
+/datum/outfit/naked
+ name = "Naked"
+
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
return
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 53c755e8822..14bc959fbb1 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -541,7 +541,7 @@
P.attack_self(H) // activate them, display musical notes effect
/datum/outfit/admin/soviet
-
+ name = "Soviet Generic"
gloves = /obj/item/clothing/gloves/combat
uniform = /obj/item/clothing/under/soviet
back = /obj/item/storage/backpack/satchel
@@ -709,7 +709,8 @@
pda = /obj/item/pda
backpack_contents = list(
/obj/item/storage/box/survival = 1,
- /obj/item/hand_labeler = 1
+ /obj/item/hand_labeler = 1,
+ /obj/item/hand_labeler_refill = 1
)
/datum/outfit/admin/sol_trader/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -771,6 +772,7 @@
apply_to_card(I, H, get_all_accesses(), "Space Explorer")
/datum/outfit/admin/hardsuit
+ name = "Hardsuit Generic"
back = /obj/item/tank/jetpack/oxygen
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/magboots
@@ -823,6 +825,7 @@
/datum/outfit/admin/tournament
+ name = "Tournament Generic"
suit = /obj/item/clothing/suit/armor/vest
shoes = /obj/item/clothing/shoes/black
head = /obj/item/clothing/head/helmet/thunderdome
@@ -1100,7 +1103,7 @@
l_hand = null
backpack_contents = list(
/obj/item/storage/box/engineer = 1,
- /obj/item/clothing/suit/space/hardsuit/shielded/wizard = 1,
+ /obj/item/clothing/suit/space/hardsuit/shielded/wizard/arch = 1,
/obj/item/clothing/shoes/magboots = 1,
/obj/item/kitchen/knife/ritual = 1,
/obj/item/clothing/suit/wizrobe/red = 1,
diff --git a/code/datums/outfits/plasmamen.dm b/code/datums/outfits/plasmamen.dm
index 376bf2af90c..94206c0ae3a 100644
--- a/code/datums/outfits/plasmamen.dm
+++ b/code/datums/outfits/plasmamen.dm
@@ -176,3 +176,9 @@
head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield
uniform = /obj/item/clothing/under/plasmaman/blueshield
+
+/datum/outfit/plasmaman/wizard
+ name = "Wizard Plasmaman"
+
+ head = /obj/item/clothing/head/helmet/space/plasmaman/wizard
+ uniform = /obj/item/clothing/under/plasmaman/wizard
diff --git a/code/datums/periodic_news.dm b/code/datums/periodic_news.dm
index d1cb9fc014d..d0d1f01ebf3 100644
--- a/code/datums/periodic_news.dm
+++ b/code/datums/periodic_news.dm
@@ -1,135 +1,123 @@
// This system defines news that will be displayed in the course of a round.
// Uses BYOND's type system to put everything into a nice format
-// THIS ISNT PROPERLY PATHED AND I AM GOING TO FUCKING SCREAM AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
/datum/news_announcement
- var
- round_time // time of the round at which this should be announced, in seconds
- message // body of the message
- author = "Nanotrasen Editor"
- channel_name = "Nyx Daily"
- can_be_redacted = 0
- message_type = "Story"
- revolution_inciting_event
+ var/round_time // time of the round at which this should be announced, in seconds
+ var/message // body of the message
+ var/author = "Nanotrasen Editor"
+ var/channel_name = "Nyx Daily"
+ var/can_be_redacted = FALSE
+ var/message_type = "Story"
- paycuts_suspicion
- round_time = 60*10
- message = {"Reports have leaked that Nanotrasen Inc. is planning to put paycuts into
- effect on many of its Research Stations in Tau Ceti. Apparently these research
- stations haven't been able to yield the expected revenue, and thus adjustments
- have to be made."}
- author = "Unauthorized"
+/datum/news_announcement/revolution_inciting_event/paycuts_suspicion
+ round_time = 60*10
+ message = {"Reports have leaked that Nanotrasen Inc. is planning to put paycuts into
+ effect on many of its Research Stations in Tau Ceti. Apparently these research
+ stations haven't been able to yield the expected revenue, and thus adjustments
+ have to be made."}
+ author = "Unauthorized"
- paycuts_confirmation
- round_time = 60*40
- message = {"Earlier rumours about paycuts on Research Stations in the Tau Ceti system have
- been confirmed. Shockingly, however, the cuts will only affect lower tier
- personnel. Heads of Staff will, according to our sources, not be affected."}
- author = "Unauthorized"
+/datum/news_announcement/revolution_inciting_event/paycuts_confirmation
+ round_time = 60*40
+ message = {"Earlier rumours about paycuts on Research Stations in the Tau Ceti system have
+ been confirmed. Shockingly, however, the cuts will only affect lower tier
+ personnel. Heads of Staff will, according to our sources, not be affected."}
+ author = "Unauthorized"
- human_experiments
- round_time = 60*90
- message = {"Unbelievable reports about human experimentation have reached our ears. According
- to a refugee from one of the Tau Ceti Research Stations, their station, in order
- to increase revenue, has refactored several of their facilities to perform experiments
- on live humans, including virology research, genetic manipulation, and \"feeding them
- to the slimes to see what happens\". Allegedly, these test subjects were neither
- humanified monkeys nor volunteers, but rather unqualified staff that were forced into
- the experiments, and reported to have died in a \"work accident\" by Nanotrasen Inc."}
- author = "Unauthorized"
+/datum/news_announcement/revolution_inciting_event/human_experiments
+ round_time = 60*90
+ message = {"Unbelievable reports about human experimentation have reached our ears. According
+ to a refugee from one of the Tau Ceti Research Stations, their station, in order
+ to increase revenue, has refactored several of their facilities to perform experiments
+ on live humans, including virology research, genetic manipulation, and \"feeding them
+ to the slimes to see what happens\". Allegedly, these test subjects were neither
+ humanified monkeys nor volunteers, but rather unqualified staff that were forced into
+ the experiments, and reported to have died in a \"work accident\" by Nanotrasen Inc."}
+ author = "Unauthorized"
- bluespace_research
+/datum/news_announcement/bluespace_research/announcement
+ round_time = 60*20
+ message = {"The new field of research trying to explain several interesting spacetime oddities,
+ also known as \"Bluespace Research\", has reached new heights. Of the several
+ hundred space stations now orbiting in Tau Ceti, fifteen are now specially equipped
+ to experiment with and research Bluespace effects. Rumours have it some of these
+ stations even sport functional \"travel gates\" that can instantly move a whole research
+ team to an alternate reality."}
- announcement
- round_time = 60*20
- message = {"The new field of research trying to explain several interesting spacetime oddities,
- also known as \"Bluespace Research\", has reached new heights. Of the several
- hundred space stations now orbiting in Tau Ceti, fifteen are now specially equipped
- to experiment with and research Bluespace effects. Rumours have it some of these
- stations even sport functional \"travel gates\" that can instantly move a whole research
- team to an alternate reality."}
+/datum/news_announcement/random_junk/cheesy_honkers
+ author = "Assistant Editor Carl Ritz"
+ channel_name = "The Gibson Gazette"
+ message = {"Do cheesy honkers increase risk of having a miscarriage? Several health administrations
+ say so!"}
+ round_time = 60 * 15
- random_junk
+/datum/news_announcement/random_junk/net_block
+ author = "Assistant Editor Carl Ritz"
+ channel_name = "The Gibson Gazette"
+ message = {"Several corporations banding together to block access to 'wetskrell.nt', site administrators
+ claiming violation of net laws."}
+ round_time = 60 * 50
- cheesy_honkers
- author = "Assistant Editor Carl Ritz"
- channel_name = "The Gibson Gazette"
- message = {"Do cheesy honkers increase risk of having a miscarriage? Several health administrations
- say so!"}
- round_time = 60 * 15
+/datum/news_announcement/random_junk/found_ssd
+ channel_name = "Nyx Daily"
+ author = "Doctor Eric Hanfield"
- net_block
- author = "Assistant Editor Carl Ritz"
- channel_name = "The Gibson Gazette"
- message = {"Several corporations banding together to block access to 'wetskrell.nt', site administrators
- claiming violation of net laws."}
- round_time = 60 * 50
+ message = {"Several people have been found unconscious at their terminals. It is thought that it was due
+ to a lack of sleep or of simply migraines from staring at the screen too long. Camera footage
+ reveals that many of them were playing games instead of working and their pay has been docked
+ accordingly."}
+ round_time = 60 * 90
- found_ssd
- channel_name = "Nyx Daily"
- author = "Doctor Eric Hanfield"
+/datum/news_announcement/lotus_tree/explosions
+ channel_name = "Nyx Daily"
+ author = "Reporter Leland H. Howards"
- message = {"Several people have been found unconscious at their terminals. It is thought that it was due
- to a lack of sleep or of simply migraines from staring at the screen too long. Camera footage
- reveals that many of them were playing games instead of working and their pay has been docked
- accordingly."}
- round_time = 60 * 90
+ message = {"The newly-christened civillian transport Lotus Tree suffered two very large explosions near the
+ bridge today, and there are unconfirmed reports that the death toll has passed 50. The cause of
+ the explosions remain unknown, but there is speculation that it might have something to do with
+ the recent change of regulation in the Moore-Lee Corporation, a major funder of the ship, when M-L
+ announced that they were officially acknowledging inter-species marriage and providing couples
+ with marriage tax-benefits."}
+ round_time = 60 * 30
- lotus_tree
+/datum/news_announcement/food_riots/breaking_news
+ channel_name = "Nyx Daily"
+ author = "Reporter Ro'kii Ar-Raqis"
- explosions
- channel_name = "Nyx Daily"
- author = "Reporter Leland H. Howards"
+ message = {"Breaking news: Food riots have broken out throughout the Refuge asteroid colony in the Tenebrae
+ Lupus system. This comes only hours after Nanotrasen officials announced they will no longer trade with the
+ colony, citing the increased presence of \"hostile factions\" on the colony has made trade too dangerous to
+ continue. Nanotrasen officials have not given any details about said factions. More on that at the top of
+ the hour."}
+ round_time = 60 * 10
- message = {"The newly-christened civillian transport Lotus Tree suffered two very large explosions near the
- bridge today, and there are unconfirmed reports that the death toll has passed 50. The cause of
- the explosions remain unknown, but there is speculation that it might have something to do with
- the recent change of regulation in the Moore-Lee Corporation, a major funder of the ship, when M-L
- announced that they were officially acknowledging inter-species marriage and providing couples
- with marriage tax-benefits."}
- round_time = 60 * 30
-
- food_riots
-
- breaking_news
- channel_name = "Nyx Daily"
- author = "Reporter Ro'kii Ar-Raqis"
-
- message = {"Breaking news: Food riots have broken out throughout the Refuge asteroid colony in the Tenebrae
- Lupus system. This comes only hours after Nanotrasen officials announced they will no longer trade with the
- colony, citing the increased presence of \"hostile factions\" on the colony has made trade too dangerous to
- continue. Nanotrasen officials have not given any details about said factions. More on that at the top of
- the hour."}
- round_time = 60 * 10
-
- more
- channel_name = "Nyx Daily"
- author = "Reporter Ro'kii Ar-Raqis"
-
- message = {"More on the Refuge food riots: The Refuge Council has condemned Nanotrasen's withdrawal from
- the colony, claiming \"there has been no increase in anti-Nanotrasen activity\", and \"\[the only] reason
- Nanotrasen withdrew was because the \[Tenebrae Lupus] system's Plasma deposits have been completely mined out.
- We have little to trade with them now\". Nanotrasen officials have denied these allegations, calling them
- \"further proof\" of the colony's anti-Nanotrasen stance. Meanwhile, Refuge Security has been unable to quell
- the riots. More on this at 6."}
- round_time = 60 * 60
+/datum/news_announcement/food_riots/more
+ channel_name = "Nyx Daily"
+ author = "Reporter Ro'kii Ar-Raqis"
+ message = {"More on the Refuge food riots: The Refuge Council has condemned Nanotrasen's withdrawal from
+ the colony, claiming \"there has been no increase in anti-Nanotrasen activity\", and \"\[the only] reason
+ Nanotrasen withdrew was because the \[Tenebrae Lupus] system's Plasma deposits have been completely mined out.
+ We have little to trade with them now\". Nanotrasen officials have denied these allegations, calling them
+ \"further proof\" of the colony's anti-Nanotrasen stance. Meanwhile, Refuge Security has been unable to quell
+ the riots. More on this at 6."}
+ round_time = 60 * 60
GLOBAL_LIST_INIT(newscaster_standard_feeds, list(/datum/news_announcement/bluespace_research, /datum/news_announcement/lotus_tree, /datum/news_announcement/random_junk, /datum/news_announcement/food_riots))
-proc/process_newscaster()
+/proc/process_newscaster()
check_for_newscaster_updates(SSticker.mode.newscaster_announcements)
GLOBAL_LIST_EMPTY(announced_news_types)
-proc/check_for_newscaster_updates(type)
+/proc/check_for_newscaster_updates(type)
for(var/subtype in subtypesof(type))
var/datum/news_announcement/news = new subtype()
if(news.round_time * 10 <= world.time && !(subtype in GLOB.announced_news_types))
GLOB.announced_news_types += subtype
announce_newscaster_news(news)
-proc/announce_newscaster_news(datum/news_announcement/news)
+/proc/announce_newscaster_news(datum/news_announcement/news)
var/datum/feed_channel/sendto
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm
index dae85c1726f..4a812b40e4e 100644
--- a/code/datums/progressbar.dm
+++ b/code/datums/progressbar.dm
@@ -39,7 +39,7 @@
if(user.client)
user.client.images += bar
- progress = Clamp(progress, 0, goal)
+ progress = clamp(progress, 0, goal)
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
if(!shown)
user.client.images += bar
diff --git a/code/datums/radio.dm b/code/datums/radio.dm
index b748a9f9229..efeebc7c973 100644
--- a/code/datums/radio.dm
+++ b/code/datums/radio.dm
@@ -1,7 +1,7 @@
/datum/radio_frequency
var/frequency as num
- var/list/list/obj/devices = list()
+ var/list/obj/devices = list()
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null)
var/turf/start_point
@@ -108,7 +108,7 @@
. = "Domestic Animal"
else
. = "Unidentifiable"
-
+
//callback used by objects to react to incoming radio signals
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return null
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index 018d5bb3496..799a12f4db9 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -175,6 +175,7 @@
description = "The crew of a space station awaken one hundred years after a crisis. Awaking to a derelict space station on the verge of collapse, and a hostile force of invading \
hivebots. Can the surviving crew overcome the odds and survive and rebuild, or will the cold embrace of the stars become their new home?"
cost = 2
+ allow_duplicates = FALSE
/datum/map_template/ruin/space/wizardcrash
id = "wizardcrash"
@@ -182,3 +183,68 @@
name = "Crashed Wizard Shuttle"
description = "A shuttle of the Wizard Federation, sent out to crush some wandless scum. Unfortunately, the pilot suffered a magic-related accident and the shuttle crashed into a nearby asteroid."
cost = 2
+
+/datum/map_template/ruin/space/abandonedtele
+ id = "abandonedtele"
+ suffix = "abandonedtele.dmm"
+ name = "Abandoned Teleporter"
+ description = "An old teleporter, seemingly part of what used to be a larger satellite."
+
+/datum/map_template/ruin/space/blowntcommsat
+ id = "blowntcommsat"
+ suffix = "blowntcommsat.dmm"
+ name = "Blown-out Telecommunications Satellite"
+ description = "The remains of an old telecommunications satellite once utilised by NanoTrasen. It lays derelict, with quite a few pieces missing."
+ cost = 5 // This is a chonky boy
+ allow_duplicates = FALSE // Absolutely huge, also has its own APC and the area isnt set to allow many
+
+/datum/map_template/ruin/space/clownmime
+ id = "clownmime"
+ suffix = "clownmime.dmm"
+ name = "Clown & Mime Mineral Deposits"
+ description = "A crash site of two opposing factions, both trying to complete mining trips for their own valuable minerals. While all the crew have long perished, the minerals are likely intact."
+
+/datum/map_template/ruin/space/dj
+ id = "dj"
+ suffix = "dj.dmm"
+ name = "Russian DJ Station"
+ description = "An old russian listening station, long since defunct and lifeless, however the equipment is likely still in working condition."
+ cost = 2
+
+/datum/map_template/ruin/space/druglab
+ id = "druglab"
+ suffix = "druglab.dmm"
+ name = "Drug Lab"
+ description = "An old abandoned \"Chemistry\" site, which has a strong aura of amphetamines around it."
+
+/datum/map_template/ruin/space/syndiedepot
+ id = "syndiedepot"
+ suffix = "syndiedepot.dmm"
+ name = "Suspicious Supply Depot"
+ description = "A syndicate supply depot, heavily stocked, but heavily guarded with an assortment of shields, sentry bots, armed operatives and more."
+ allow_duplicates = FALSE // One of these is enough
+ always_place = TRUE // This is on the always spawn list because of the shielding chance
+ cost = 0 // Force spawned so shouldnt have a cost
+
+/datum/map_template/ruin/space/ussp_tele
+ id = "ussp_tele"
+ suffix = "ussp_tele.dmm"
+ name = "USSP Teleporter"
+ description = "An old, almost fully destroyed teleporter, seemingly part of what used to be a much larger structure."
+
+/datum/map_template/ruin/space/ussp
+ id = "ussp"
+ suffix = "ussp.dmm"
+ name = "USSP"
+ description = "A decript station of seemingly russian origin. The last contact had with this station was a distress signal, and the rest was dark."
+ allow_duplicates = FALSE // One of these has enough loot
+ cost = 5 // This ruin is 100x100 tiles, so we dont want it to be treated like a 10x10 meteor
+
+/datum/map_template/ruin/space/whiteship
+ id = "whiteship"
+ suffix = "whiteship.dmm"
+ name = "NT Medical Ship"
+ description = "An old, abandoned NT medical ship. Its computer can navigate to other landmarks within space with ease."
+ allow_duplicates = FALSE // I dont even want to think about what happens if you have 2 shuttles with the same ID. Likely scary stuff.
+ always_place = TRUE // Its designed to make exploring other space ruins more accessible
+ cost = 0 // Force spawned so shouldnt have a cost
diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm
index 53517d5dbc9..4d6310041e5 100644
--- a/code/datums/shuttles.dm
+++ b/code/datums/shuttles.dm
@@ -9,8 +9,9 @@
var/admin_notes
/datum/map_template/shuttle/New()
- shuttle_id = "[port_id]_[suffix]"
- mappath = "[prefix][shuttle_id].dmm"
+ if(port_id && suffix)
+ shuttle_id = "[port_id]_[suffix]"
+ mappath = "[prefix][shuttle_id].dmm"
. = ..()
/datum/map_template/shuttle/emergency
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 30347d1e796..3855dbcfac3 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -237,11 +237,11 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
if(action)
action.UpdateButtonIcon()
-/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr) //if recharge is started is important for the trigger spells
+/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr, make_attack_logs = TRUE) //if recharge is started is important for the trigger spells
before_cast(targets)
invocation()
- if(user && user.ckey)
- add_attack_logs(user, null, "cast the spell [name]")
+ if(user && user.ckey && make_attack_logs)
+ add_attack_logs(user, targets, "cast the spell [name]", ATKLOG_ALL)
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm
index 8a3585febc0..0d24a984014 100644
--- a/code/datums/spells/area_teleport.dm
+++ b/code/datums/spells/area_teleport.dm
@@ -79,6 +79,8 @@
target.forceMove(pick(L))
playsound(get_turf(user), sound2, 50,1)
+ user.update_action_buttons_icon() //Update action buttons as some spells might now be castable
+
return
/obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null)
diff --git a/code/datums/spells/cluwne.dm b/code/datums/spells/cluwne.dm
index 91df261e9c2..19a12055fef 100644
--- a/code/datums/spells/cluwne.dm
+++ b/code/datums/spells/cluwne.dm
@@ -36,10 +36,10 @@
unEquip(gloves, 1)
if(!istype(wear_mask, /obj/item/clothing/mask/cursedclown)) //Infinite loops otherwise
unEquip(wear_mask, 1)
- equip_to_slot_if_possible(new /obj/item/clothing/under/cursedclown, slot_w_uniform, 1, 1, 1)
- equip_to_slot_if_possible(new /obj/item/clothing/gloves/cursedclown, slot_gloves, 1, 1, 1)
- equip_to_slot_if_possible(new /obj/item/clothing/mask/cursedclown, slot_wear_mask, 1, 1, 1)
- equip_to_slot_if_possible(new /obj/item/clothing/shoes/cursedclown, slot_shoes, 1, 1, 1)
+ equip_to_slot_if_possible(new /obj/item/clothing/under/cursedclown, slot_w_uniform, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/gloves/cursedclown, slot_gloves, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/mask/cursedclown, slot_wear_mask, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/shoes/cursedclown, slot_shoes, TRUE, TRUE)
/mob/living/carbon/human/proc/makeAntiCluwne()
to_chat(src, "You don't feel very funny.")
@@ -83,5 +83,5 @@
unEquip(gloves, 1)
qdel(G)
- equip_to_slot_if_possible(new /obj/item/clothing/under/lawyer/black, slot_w_uniform, 1, 1, 1)
- equip_to_slot_if_possible(new /obj/item/clothing/shoes/black, slot_shoes, 1, 1, 1)
+ equip_to_slot_if_possible(new /obj/item/clothing/under/lawyer/black, slot_w_uniform, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/shoes/black, slot_shoes, TRUE, TRUE)
diff --git a/code/datums/spells/devil.dm b/code/datums/spells/devil.dm
index 12e2a44a8c1..27b2fcb8851 100644
--- a/code/datums/spells/devil.dm
+++ b/code/datums/spells/devil.dm
@@ -142,7 +142,6 @@
return 0
fakefire()
forceMove(get_turf(src))
- reset_perspective()
visible_message("[src] appears in a firey blaze!")
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1)
spawn(15)
diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm
index 3c2f997e461..d95c6212486 100644
--- a/code/datums/spells/genetic.dm
+++ b/code/datums/spells/genetic.dm
@@ -2,7 +2,6 @@
name = "Genetic"
desc = "This spell inflicts a set of mutations and disabilities upon the target."
- var/disabilities = 0 //bits
var/list/mutations = list() //mutation strings
var/duration = 100 //deciseconds
/*
@@ -20,16 +19,12 @@
for(var/mob/living/target in targets)
for(var/x in mutations)
target.mutations.Add(x)
- /* if(x == HULK && ishuman(target))
- target:hulk_time=world.time + duration */
- target.disabilities |= disabilities
target.update_mutations() //update target's mutation overlays
var/mob/living/carbon/human/H = target
if(ishuman(target))
H.update_body()
spawn(duration)
target.mutations.Remove(mutations)
- target.disabilities &= ~disabilities
target.update_mutations()
if(ishuman(target))
H.update_body()
diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm
index 2c000a0d232..0140fbdf951 100644
--- a/code/datums/spells/horsemask.dm
+++ b/code/datums/spells/horsemask.dm
@@ -43,6 +43,6 @@
"Your face burns up, and shortly after the fire you realise you have the face of a horse!")
if(!target.unEquip(target.wear_mask))
qdel(target.wear_mask)
- target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
+ target.equip_to_slot_if_possible(magichead, slot_wear_mask, TRUE, TRUE)
target.flash_eyes()
diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm
index dc2efcc1e91..88f5eec9474 100644
--- a/code/datums/spells/knock.dm
+++ b/code/datums/spells/knock.dm
@@ -13,6 +13,11 @@
action_icon_state = "knock"
sound = 'sound/magic/knock.ogg'
+// Knock doesn't need to generate an attack log for every turf, set `make_attack_logs` to FALSE and just create a custom one.
+/obj/effect/proc_holder/spell/aoe_turf/knock/perform(list/targets, recharge, mob/user)
+ add_attack_logs(user, user, "cast the spell [name]", ATKLOG_ALL)
+ return ..(targets, recharge, user, make_attack_logs = FALSE)
+
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets, mob/user = usr)
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
@@ -30,8 +35,6 @@
SC.locked = 0
C.open()
- return
-
/obj/effect/proc_holder/spell/aoe_turf/knock/greater
name = "Greater Knock"
desc = "On first cast, will remove access restrictions on all airlocks on the station, and announce this spell's use to the station. On any further cast, will open all doors in sight. Cannot be refunded once bought!"
diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm
index 9db46b517db..9175fd677fb 100644
--- a/code/datums/spells/lichdom.dm
+++ b/code/datums/spells/lichdom.dm
@@ -28,7 +28,7 @@
config.continuous_rounds = 0
return ..()
-/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
+/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets, mob/user = usr)
if(!config.continuous_rounds)
existence_stops_round_end = 1
config.continuous_rounds = 1
@@ -36,7 +36,7 @@
for(var/mob/M in targets)
var/list/hand_items = list()
if(iscarbon(M))
- hand_items = list(M.get_active_hand(),M.get_inactive_hand())
+ hand_items = list(M.get_active_hand(), M.get_inactive_hand())
if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry
marked_item = null
@@ -74,12 +74,9 @@
var/mob/old_body = current_body
var/turf/body_turf = get_turf(old_body)
current_body = lich
- lich.Weaken(10+10*resurrections)
+ lich.Weaken(10 + 10 * resurrections)
++resurrections
- lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes)
- lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
- lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
- lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
+ equip_lich(lich)
if(old_body && old_body.loc)
if(iscarbon(old_body))
@@ -95,7 +92,7 @@
if(!marked_item) //linking item to the spell
message = ""
for(var/obj/item in hand_items)
- if(ABSTRACT in item.flags || NODROP in item.flags)
+ if((ABSTRACT in item.flags) || (NODROP in item.flags))
continue
marked_item = item
to_chat(M, "You begin to focus your very being into the [item.name]...")
@@ -127,7 +124,10 @@
H.unEquip(H.head)
H.unEquip(H.shoes)
H.unEquip(H.head)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
+ equip_lich(H)
+
+/obj/effect/proc_holder/spell/targeted/lichdom/proc/equip_lich(mob/living/carbon/human/H)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm
index d0c052649d9..11b0a75b275 100644
--- a/code/datums/spells/mime.dm
+++ b/code/datums/spells/mime.dm
@@ -165,4 +165,4 @@
/obj/item/spellbook/oneuse/mime/greaterwall
spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
spellname = "Invisible Greater Wall"
- desc = "It contains illustrations of the great walls of human history."
\ No newline at end of file
+ desc = "It contains illustrations of the great walls of human history."
diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm
index aaef2229856..a0c41b57001 100644
--- a/code/datums/spells/summonitem.dm
+++ b/code/datums/spells/summonitem.dm
@@ -41,7 +41,7 @@
else
message = "You must hold the desired item in your hands to mark it for recall."
- else if(marked_item && marked_item in hand_items) //unlinking item to the spell
+ else if(marked_item && (marked_item in hand_items)) //unlinking item to the spell
message = "You remove the mark on [marked_item] to use elsewhere."
name = "Instant Summons"
marked_item = null
@@ -75,8 +75,6 @@
B.transfer_identity(C)
C.death()
add_attack_logs(target, C, "Magically debrained INTENT: [uppertext(target.a_intent)]")*/
- if(C.stomach_contents && item_to_retrieve in C.stomach_contents)
- C.stomach_contents -= item_to_retrieve
for(var/X in C.bodyparts)
var/obj/item/organ/external/part = X
if(item_to_retrieve in part.embedded_objects)
@@ -104,12 +102,12 @@
if(target.hand) //left active hand
- if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1))
- if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1))
+ if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, FALSE, TRUE))
+ if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, FALSE, TRUE))
butterfingers = 1
else //right active hand
- if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1))
- if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1))
+ if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, FALSE, TRUE))
+ if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, FALSE, TRUE))
butterfingers = 1
if(butterfingers)
item_to_retrieve.loc = target.loc
diff --git a/code/datums/spells/touch_attacks.dm b/code/datums/spells/touch_attacks.dm
index d656bccac4a..c242a1aa52f 100644
--- a/code/datums/spells/touch_attacks.dm
+++ b/code/datums/spells/touch_attacks.dm
@@ -27,12 +27,12 @@
var/hand_handled = 1
attached_hand = new hand_path(src)
if(user.hand) //left active hand
- if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1))
- if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1))
+ if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, FALSE, TRUE))
+ if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, FALSE, TRUE))
hand_handled = 0
else //right active hand
- if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1))
- if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1))
+ if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, FALSE, TRUE))
+ if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, FALSE, TRUE))
hand_handled = 0
if(!hand_handled)
qdel(attached_hand)
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index cf7e6fa3217..94383f1b1e2 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -304,7 +304,7 @@
sound = 'sound/magic/blind.ogg'
/obj/effect/proc_holder/spell/targeted/genetic/blind
- disabilities = BLIND
+ mutations = list(BLINDNESS)
duration = 300
sound = 'sound/magic/blind.ogg'
@@ -423,7 +423,7 @@
M.Weaken(stun_amt)
to_chat(M, "You're thrown back by a mystical force!")
spawn(0)
- AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
+ AM.throw_at(throwtarget, ((clamp((maxthrow - (clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/targeted/sacred_flame
name = "Sacred Flame"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 5ded7fa43a4..61decede9bc 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -190,7 +190,7 @@
L.adjustBrainLoss(-3.5)
L.adjustCloneLoss(-1) //Becasue apparently clone damage is the bastion of all health
if(ishuman(L))
- var/var/mob/living/carbon/human/H = L
+ var/mob/living/carbon/human/H = L
for(var/obj/item/organ/external/E in H.bodyparts)
if(prob(10))
E.mend_fracture()
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 896f4f999a9..2580b1c9935 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -5,7 +5,7 @@
/datum/status_effect
var/id = "effect" //Used for screen alerts.
var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means.
- var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
+ var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second. Setting this to -1 will stop processing if duration is also unlimited.
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
@@ -31,7 +31,8 @@
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
A.attached_effect = src //so the alert can reference us, if it needs to
linked_alert = A //so we can reference the alert, if we need to
- START_PROCESSING(SSfastprocess, src)
+ if(duration > 0 || initial(tick_interval) > 0) //don't process if we don't care
+ START_PROCESSING(SSfastprocess, src)
return TRUE
/datum/status_effect/Destroy()
@@ -41,6 +42,9 @@
LAZYREMOVE(owner.status_effects, src)
on_remove()
owner = null
+ if(linked_alert)
+ linked_alert.attached_effect = null
+ linked_alert = null
return ..()
/datum/status_effect/process()
@@ -85,6 +89,13 @@
desc = "You don't feel any different..."
var/datum/status_effect/attached_effect
+/obj/screen/alert/status_effect/Destroy()
+ if(attached_effect)
+ attached_effect.linked_alert = null
+ attached_effect = null
+ return ..()
+
+
//////////////////
// HELPER PROCS //
//////////////////
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 91e68da427b..5b21036b2bc 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -633,7 +633,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
contains = list(/obj/machinery/power/emitter,
/obj/machinery/power/emitter)
cost = 10
- containertype = /obj/structure/closet/crate/secure
containername = "emitter crate"
access = ACCESS_CE
containertype = /obj/structure/closet/crate/secure/engineering
@@ -717,7 +716,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
name = "Supermatter Shard Crate"
contains = list(/obj/machinery/power/supermatter_shard)
cost = 50 //So cargo thinks twice before killing themselves with it
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/engineering
containername = "supermatter shard crate"
access = ACCESS_CE
@@ -728,7 +727,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
/obj/item/pipe/circulator,
/obj/item/pipe/circulator)
cost = 25
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/engineering
containername = "thermo-electric generator crate"
access = ACCESS_CE
announce_beacons = list("Engineering" = list("Chief Engineer's Desk", "Atmospherics"))
@@ -1204,7 +1203,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containername = "hydroponics crate"
announce_beacons = list("Hydroponics" = list("Hydroponics"))
-/datum/supply_packs/misc/hydroponics/hydrotank
+/datum/supply_packs/organic/hydroponics/hydrotank
name = "Hydroponics Watertank Crate"
contains = list(/obj/item/watertank)
cost = 10
@@ -1434,6 +1433,8 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
contains = list(/obj/structure/filingcabinet/chestdrawer,
/obj/item/camera_film,
/obj/item/hand_labeler,
+ /obj/item/hand_labeler_refill,
+ /obj/item/hand_labeler_refill,
/obj/item/stack/tape_roll,
/obj/item/paper_bin,
/obj/item/pen,
@@ -1765,6 +1766,16 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
cost = 20
containername = "polo supply crate"
+/datum/supply_packs/misc/boxing //For non log spamming cargo brawls!
+ name = "Boxing Supply Crate"
+ // 4 boxing gloves
+ contains = list(/obj/item/clothing/gloves/boxing/blue,
+ /obj/item/clothing/gloves/boxing/green,
+ /obj/item/clothing/gloves/boxing/yellow,
+ /obj/item/clothing/gloves/boxing)
+ cost = 15
+ containername = "boxing supply crate"
+
///////////// Station Goals
/datum/supply_packs/misc/station_goal
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index a5155cceb4a..4814e27380b 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -108,7 +108,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
return desc
/datum/uplink_item/proc/buy(var/obj/item/uplink/hidden/U, var/mob/user)
- ..()
if(!istype(U))
return 0
@@ -189,15 +188,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/storage/box/syndie_kit/fake_revolver
cost = 1
job = list("Clown")
-/*
-/datum/uplink_item/stealthy_weapons/romerol_kit
- name = "Romerol"
- reference = "ROM"
- desc = "A highly experimental bioterror agent which creates dormant nodules to be etched into the grey matter of the brain. On death, these nodules take control of the dead body, causing limited revivification, along with slurred speech, aggression, and the ability to infect others with this agent."
- item = /obj/item/storage/box/syndie_kit/romerol
- cost = 25
- cant_discount = TRUE
-*/
//mime
/datum/uplink_item/jobspecific/caneshotgun
name = "Cane Shotgun and Assassination Shells"
@@ -248,6 +238,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
job = list("Chef")
+/datum/uplink_item/jobspecific/Chef_CQC
+ name = " A chefs manual to CQC"
+ desc = "An old manual teaching you how to bring your home advantage outside the kitchen."
+ reference = "CCQC"
+ item = /obj/item/CQC_manual/chef
+ cost = 12
+ job = list("Chef")
+
//Chaplain
/datum/uplink_item/jobspecific/voodoo
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index e3d90b8d075..dcde08d7ec1 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -166,9 +166,9 @@
//raises them if they are down (only if power's on)
if(!A.locked)
if(A.lock())
- A.audible_message("You hear a click from the bottom of the door.", null, 1)
+ A.audible_message("You hear a click from the bottom of the door.", hearing_distance = 1)
else if(A.unlock())
- A.audible_message("You hear a click from the bottom of the door.", null, 1)
+ A.audible_message("You hear a click from the bottom of the door.", hearing_distance = 1)
if(AIRLOCK_WIRE_BACKUP_POWER1)
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index 789a0472869..04a9509cfe2 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -15,16 +15,16 @@
switch(index)
if(BORG_WIRE_MAIN_POWER)
return "Main Power"
-
+
if(BORG_WIRE_LOCKED_DOWN)
return "Lockdown"
-
+
if(BORG_WIRE_CAMERA)
return "Camera"
-
+
if(BORG_WIRE_AI_CONTROL)
return "AI Control"
-
+
if(BORG_WIRE_LAWCHECK)
return "Law Check"
@@ -52,7 +52,7 @@
if(BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
if(!mended)
if(R.connected_ai)
- R.connected_ai = null
+ R.disconnect_from_ai()
if(BORG_WIRE_CAMERA)
if(!isnull(R.camera) && !R.scrambledcodes)
@@ -74,8 +74,7 @@
switch(index)
if(BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!R.emagged)
- R.connected_ai = select_active_ai()
- R.notify_ai(1)
+ R.connect_to_ai(select_active_ai())
if(BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index b490d150efe..430b5ce88aa 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -96,7 +96,6 @@
if(BOMB_WIRE_ACTIVATE)
if(!mended && B.active)
holder.visible_message("[bicon(B)] The timer stops! The bomb has been defused!")
- B.active = FALSE
B.defused = TRUE
B.update_icon()
..()
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index 1a407f2ec50..09c874ce8a8 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -31,7 +31,6 @@ GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "b
src.holder = holder
if(!istype(holder, holder_type))
CRASH("Our holder is null/the wrong type!")
- return
// Generate new wires
if(random)
@@ -87,7 +86,7 @@ GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "b
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
- if(eyes && H.disabilities & COLOURBLIND)
+ if(eyes && (COLOURBLIND in H.mutations))
replace_colours = eyes.replace_colours
diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm
index b7036f9fbdc..23b485ad252 100644
--- a/code/defines/procs/admin.dm
+++ b/code/defines/procs/admin.dm
@@ -7,7 +7,7 @@
/proc/key_name_helper(whom, include_name, include_link = FALSE, type = null)
if(include_link != FALSE && include_link != TRUE)
- log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]"), src)
+ log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]"))
var/mob/M
var/client/C
@@ -83,10 +83,6 @@
var/message = "[key_name(whom, 0)][isAntag(whom) ? "(ANTAG)" : ""][isLivingSSD(whom) ? "(SSD!)": ""]"
return message
-/proc/log_and_message_admins(var/message as text)
+/proc/log_and_message_admins(message)
log_admin("[key_name(usr)] " + message)
message_admins("[key_name_admin(usr)] " + message)
-
-/proc/admin_log_and_message_admins(var/message as text)
- log_admin("[key_name(usr)] " + message)
- message_admins("[key_name_admin(usr)] " + message, 1)
diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm
index 76e5a1fd0a6..90a5b0db40c 100644
--- a/code/defines/procs/dbcore.dm
+++ b/code/defines/procs/dbcore.dm
@@ -72,12 +72,21 @@ DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return n
DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler)
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "DB query blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to create a DB query via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to create a DB query via advanced proc-call")
+ return
if(sql_query) src.sql = sql_query
if(connection_handler) src.db_connection = connection_handler
if(cursor_handler) src.default_cursor = cursor_handler
_db_query = _dm_db_new_query()
return ..()
+DBQuery/CanProcCall()
+ // dont even try it
+ return FALSE
+
DBQuery
var/sql // The sql query being executed.
diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm
index a3d6647ef41..7c0dc4de7f8 100644
--- a/code/defines/procs/radio.dm
+++ b/code/defines/procs/radio.dm
@@ -24,62 +24,9 @@
return freq_text
-/datum/reception
- var/obj/machinery/message_server/message_server = null
- var/telecomms_reception = TELECOMMS_RECEPTION_NONE
- var/message = ""
-
-/datum/receptions
- var/obj/machinery/message_server/message_server = null
- var/sender_reception = TELECOMMS_RECEPTION_NONE
- var/list/receiver_reception = new
-
/proc/get_message_server()
if(GLOB.message_servers)
for(var/obj/machinery/message_server/MS in GLOB.message_servers)
if(MS.active)
return MS
return null
-
-/proc/check_signal(var/datum/signal/signal)
- return signal && signal.data["done"]
-
-/proc/get_sender_reception(var/atom/sender, var/datum/signal/signal)
- return check_signal(signal) ? TELECOMMS_RECEPTION_SENDER : TELECOMMS_RECEPTION_NONE
-
-/proc/get_receiver_reception(var/receiver, var/datum/signal/signal)
- if(receiver && check_signal(signal))
- var/turf/pos = get_turf(receiver)
- // Maybe should get tie-in to the space manager?
- if(pos && (pos.z in signal.data["level"]))
- return TELECOMMS_RECEPTION_RECEIVER
- return TELECOMMS_RECEPTION_NONE
-
-/proc/get_reception(var/atom/sender, var/receiver, var/message = "", var/do_sleep = 1)
- var/datum/reception/reception = new
-
- // check if telecomms I/O route 1459 is stable
- reception.message_server = get_message_server()
-
- var/datum/signal/signal = sender.telecomms_process(do_sleep) // Be aware that this proc calls sleep, to simulate transmition delays
- reception.telecomms_reception |= get_sender_reception(sender, signal)
- reception.telecomms_reception |= get_receiver_reception(receiver, signal)
- reception.message = signal && signal.data["compression"] > 0 ? Gibberish(message, signal.data["compression"] + 50) : message
-
- return reception
-
-/proc/get_receptions(var/atom/sender, var/list/atom/receivers, var/do_sleep = 1)
- var/datum/receptions/receptions = new
- receptions.message_server = get_message_server()
-
- var/datum/signal/signal
- if(sender)
- signal = sender.telecomms_process(do_sleep)
- receptions.sender_reception = get_sender_reception(sender, signal)
-
- for(var/atom/receiver in receivers)
- if(!signal)
- signal = receiver.telecomms_process()
- receptions.receiver_reception[receiver] = get_receiver_reception(receiver, signal)
-
- return receptions
diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm
index e6e111880fb..8f3eeeaa6fa 100644
--- a/code/defines/procs/statistics.dm
+++ b/code/defines/procs/statistics.dm
@@ -1,35 +1,3 @@
-/proc/sql_poll_players()
- if(!config.sql_enabled)
- return
- var/playercount = 0
- for(var/mob/M in GLOB.player_list)
- if(M.client)
- playercount += 1
- establish_db_connection()
- if(!GLOB.dbcon.IsConnected())
- log_game("SQL ERROR during player polling. Failed to connect.")
- else
- var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
- var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, time) VALUES ([playercount], '[sqltime]')")
- if(!query.Execute())
- var/err = query.ErrorMsg()
- log_game("SQL ERROR during player polling. Error : \[[err]\]\n")
-
-
-/proc/sql_poll_admins()
- if(!config.sql_enabled)
- return
- var/admincount = GLOB.admins.len
- establish_db_connection()
- if(!GLOB.dbcon.IsConnected())
- log_game("SQL ERROR during admin polling. Failed to connect.")
- else
- var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
- var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (admincount, time) VALUES ([admincount], '[sqltime]')")
- if(!query.Execute())
- var/err = query.ErrorMsg()
- log_game("SQL ERROR during admin polling. Error : \[[err]\]\n")
-
/proc/sql_report_round_start()
// TODO
if(!config.sql_enabled)
@@ -61,8 +29,9 @@
var/laname
var/lakey
if(H.lastattacker)
- laname = sanitizeSQL(H.lastattacker:real_name)
- lakey = sanitizeSQL(H.lastattacker:key)
+ laname = sanitizeSQL(H.lastattacker)
+ if(H.lastattackerckey)
+ lakey = sanitizeSQL(H.lastattackerckey)
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/coord = "[H.x], [H.y], [H.z]"
// to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()])")
@@ -96,8 +65,9 @@
var/laname
var/lakey
if(H.lastattacker)
- laname = sanitizeSQL(H.lastattacker:real_name)
- lakey = sanitizeSQL(H.lastattacker:key)
+ laname = sanitizeSQL(H.lastattacker)
+ if(H.lastattackerckey)
+ lakey = sanitizeSQL(H.lastattackerckey)
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/coord = "[H.x], [H.y], [H.z]"
// to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])")
@@ -110,15 +80,6 @@
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
-/proc/statistic_cycle()
- if(!config.sql_enabled)
- return
- while(1)
- sql_poll_players()
- sleep(600)
- sql_poll_admins()
- sleep(6000) //Poll every ten minutes
-
//This proc is used for feedback. It is executed at round end.
/proc/sql_commit_feedback()
if(!GLOB.blackbox)
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index bbfcc915c79..c33e7609685 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -13,35 +13,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
*/
-/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
-/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
-GLOBAL_LIST_EMPTY(teleportlocs)
-/hook/startup/proc/process_teleport_locs()
- for(var/area/AR in world)
- if(AR.no_teleportlocs) continue
- if(GLOB.teleportlocs.Find(AR.name)) continue
- var/turf/picked = safepick(get_area_turfs(AR.type))
- if(picked && is_station_level(picked.z))
- GLOB.teleportlocs += AR.name
- GLOB.teleportlocs[AR.name] = AR
-
- GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs)
-
- return 1
-
-GLOBAL_LIST_EMPTY(ghostteleportlocs)
-/hook/startup/proc/process_ghost_teleport_locs()
- for(var/area/AR in world)
- if(GLOB.ghostteleportlocs.Find(AR.name)) continue
- var/list/turfs = get_area_turfs(AR.type)
- if(turfs.len)
- GLOB.ghostteleportlocs += AR.name
- GLOB.ghostteleportlocs[AR.name] = AR
-
- GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
-
- return 1
-
/*-----------------------------------------------------------------------------*/
@@ -70,7 +41,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
power_environ = FALSE
valid_territory = FALSE
outdoors = TRUE
- ambientsounds = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/traitor.ogg')
+ ambientsounds = SPACE_SOUNDS
/area/space/nearstation
icon_state = "space_near"
@@ -117,39 +88,33 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/escape
name = "\improper Emergency Shuttle"
- music = "music/escape.ogg"
icon_state = "shuttle2"
nad_allowed = TRUE
/area/shuttle/pod_1
name = "\improper Escape Pod One"
- music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
/area/shuttle/pod_2
name = "\improper Escape Pod Two"
- music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
/area/shuttle/pod_3
name = "\improper Escape Pod Three"
- music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
parallax_movedir = EAST
/area/shuttle/pod_4
name = "\improper Escape Pod Four"
- music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
parallax_movedir = EAST
/area/shuttle/escape_pod1
name = "\improper Escape Pod One"
- music = "music/escape.ogg"
nad_allowed = TRUE
/area/shuttle/escape_pod1/station
@@ -163,7 +128,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/escape_pod2
name = "\improper Escape Pod Two"
- music = "music/escape.ogg"
nad_allowed = TRUE
/area/shuttle/escape_pod2/station
@@ -177,7 +141,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/escape_pod3
name = "\improper Escape Pod Three"
- music = "music/escape.ogg"
nad_allowed = TRUE
/area/shuttle/escape_pod3/station
@@ -191,7 +154,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/escape_pod5 //Pod 4 was lost to meteors
name = "\improper Escape Pod Five"
- music = "music/escape.ogg"
nad_allowed = TRUE
/area/shuttle/escape_pod5/station
@@ -205,7 +167,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/mining
name = "\improper Mining Shuttle"
- music = "music/escape.ogg"
icon_state = "shuttle"
/area/shuttle/transport
@@ -246,7 +207,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/siberia
name = "\improper Labor Camp Shuttle"
- music = "music/escape.ogg"
icon_state = "shuttle"
/area/shuttle/specops
@@ -329,7 +289,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/shuttle/research
name = "\improper Research Shuttle"
- music = "music/escape.ogg"
icon_state = "shuttle"
/area/shuttle/research/station
@@ -498,6 +457,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
nad_allowed = TRUE
+ ambientsounds = HIGHSEC_SOUNDS
/area/syndicate_mothership/control
name = "\improper Syndicate Control Room"
@@ -519,6 +479,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
requires_power = FALSE
valid_territory = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+ ambientsounds = MINING_SOUNDS
/area/asteroid/cave // -- TLE
name = "\improper Asteroid - Underground"
@@ -565,6 +526,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/exploration/methlab
name = "\improper Abandoned Drug Lab"
icon_state = "green"
+ there_can_be_many = TRUE
//Abductors
/area/abductor_ship
@@ -633,7 +595,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
//Maintenance
/area/maintenance
- ambientsounds = list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg', 'sound/ambience/ambimaint5.ogg')
+ ambientsounds = MAINTENANCE_SOUNDS
valid_territory = FALSE
/area/maintenance/atmos_control
@@ -688,10 +650,6 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
name = "Engineering Maintenance"
icon_state = "amaint"
-/area/maintenance/engi_shuttle
- name = "Engineering Shuttle Access"
- icon_state = "maint_e_shuttle"
-
/area/maintenance/storage
name = "Atmospherics Maintenance"
icon_state = "green"
@@ -803,12 +761,11 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/bridge
name = "\improper Bridge"
icon_state = "bridge"
- music = "signal"
+ ambientsounds = list('sound/ambience/signal.ogg')
/area/bridge/meeting_room
name = "\improper Heads of Staff Meeting Room"
icon_state = "meeting"
- music = null
/area/crew_quarters/captain
name = "\improper Captain's Office"
@@ -969,10 +926,12 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
name = "\improper Abandoned Library"
icon_state = "library"
+/area/chapel
+ icon_state = "chapel"
+ ambientsounds = HOLY_SOUNDS
+
/area/chapel/main
name = "\improper Chapel"
- icon_state = "chapel"
- ambientsounds = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
/area/chapel/office
name = "\improper Chapel Office"
@@ -1107,7 +1066,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
//Engineering
/area/engine
- ambientsounds = list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
+ ambientsounds = ENGINEERING_SOUNDS
/area/engine/engine_smes
name = "\improper Engineering SMES"
@@ -1161,6 +1120,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
requires_power = FALSE
valid_territory = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
+ ambientsounds = ENGINEERING_SOUNDS
/area/solar/auxport
name = "\improper Fore Port Solar Array"
@@ -1227,18 +1187,18 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/teleporter
name = "\improper Teleporter"
icon_state = "teleporter"
- music = "signal"
+ ambientsounds = ENGINEERING_SOUNDS
/area/gateway
name = "\improper Gateway"
icon_state = "teleporter"
- music = "signal"
+ ambientsounds = ENGINEERING_SOUNDS
/area/AIsattele
name = "\improper Abandoned Teleporter"
icon_state = "teleporter"
- music = "signal"
- ambientsounds = list('sound/ambience/ambimalf.ogg')
+ ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/signal.ogg')
+ there_can_be_many = TRUE
/area/toxins/explab
name = "\improper E.X.P.E.R.I-MENTOR Lab"
@@ -1250,42 +1210,39 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
//MedBay
+/area/medical
+ ambientsounds = MEDICAL_SOUNDS
+
/area/medical/medbay
name = "\improper Medbay"
icon_state = "medbay"
- music = 'sound/ambience/signal.ogg'
//Medbay is a large area, these additional areas help level out APC load.
/area/medical/medbay2
name = "\improper Medbay"
icon_state = "medbay2"
- music = 'sound/ambience/signal.ogg'
/area/medical/medbay3
name = "\improper Medbay"
icon_state = "medbay3"
- music = 'sound/ambience/signal.ogg'
/area/medical/biostorage
name = "\improper Medical Storage"
icon_state = "medbaysecstorage"
- music = 'sound/ambience/signal.ogg'
/area/medical/reception
name = "\improper Medbay Reception"
icon_state = "medbay"
- music = 'sound/ambience/signal.ogg'
/area/medical/psych
name = "\improper Psych Room"
icon_state = "medbaypsych"
- music = 'sound/ambience/signal.ogg'
+ ambientsounds = list('sound/ambience/aurora_caelus_short.ogg')
/area/medical/medbreak
name = "\improper Break Room"
icon_state = "medbaybreak"
- music = 'sound/ambience/signal.ogg'
/area/medical/patients_rooms
name = "\improper Patient's Rooms"
@@ -1342,7 +1299,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/medical/morgue
name = "\improper Morgue"
icon_state = "morgue"
- ambientsounds = list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg')
+ ambientsounds = SPOOKY_SOUNDS
/area/medical/chemistry
name = "\improper Chemistry"
@@ -1390,6 +1347,9 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
//Security
+/area/security
+ ambientsounds = HIGHSEC_SOUNDS
+
/area/security/main
name = "\improper Security Office"
icon_state = "securityoffice"
@@ -1522,6 +1482,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/security/detectives_office
name = "\improper Detective's Office"
icon_state = "detective"
+ ambientsounds = list('sound/ambience/ambidet1.ogg', 'sound/ambience/ambidet2.ogg')
/area/security/range
name = "\improper Firing Range"
@@ -1748,6 +1709,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/djstation
name = "\improper Ruskie DJ Station"
icon_state = "DJ"
+ there_can_be_many = TRUE
/area/djstation/solars
name = "\improper Ruskie DJ Station Solars"
@@ -1824,6 +1786,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/derelict/teleporter
name = "\improper Derelict Teleporter"
icon_state = "teleporter"
+ there_can_be_many = TRUE
/area/derelict/eva
name = "Derelict EVA Storage"
@@ -1865,84 +1828,12 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
name = "Derelict Atmospherics"
icon_state = "red"
-//HALF-BUILT STATION (REPLACES DERELICT IN BAYCODE, ABOVE IS LEFT FOR DOWNSTREAM)
-
-/area/shuttle/constructionsite
- name = "\improper Construction Site Shuttle"
- icon_state = "yellow"
- parallax_movedir = EAST
-
-/area/shuttle/constructionsite/station
- name = "\improper Construction Site Shuttle"
-
-/area/shuttle/constructionsite/site
- name = "\improper Construction Site Shuttle"
-
-/area/constructionsite
- name = "\improper Construction Site"
- icon_state = "storage"
-
-/area/constructionsite/storage
- name = "\improper Construction Site Storage Area"
-
-/area/constructionsite/science
- name = "\improper Construction Site Research"
- icon_state = "medresearch"
-
-/area/constructionsite/bridge
- name = "\improper Construction Site Bridge"
- icon_state = "bridge"
-
-/area/constructionsite/hallway/center
- name = "\improper Construction Site Central Hallway"
- icon_state = "hallC"
-
-/area/constructionsite/hallway/engcore
- name = "\improper Construction Site Eng Core"
- icon_state = "green"
-
-/area/constructionsite/hallway/fore
- name = "\improper Construction Site Fore"
- icon_state = "green"
-
-/area/constructionsite/hallway/port
- name = "\improper Construction Site Port"
- icon_state = "hallP"
-
-/area/constructionsite/hallway/aft
- name = "\improper Construction Site Aft"
- icon_state = "hallA"
-
-/area/constructionsite/hallway/starboard
- name = "\improper Construction Site Starboard"
- icon_state = "hallS"
-
-/area/constructionsite/atmospherics
- name = "\improper Construction Site Atmospherics"
- icon_state = "atmos"
-
-/area/constructionsite/medical
- name = "\improper Construction Site Medbay"
- icon_state = "medbay"
-
-/area/constructionsite/ai
- name = "\improper Construction Computer Core"
- icon_state = "ai"
-
-/area/constructionsite/engineering
- name = "\improper Construction Site Engine Bay"
- icon_state = "engine"
-
-/area/solar/constructionsite
- name = "\improper Construction Site Solars"
- icon_state = "panelsA"
-
-
//Construction
/area/construction
name = "\improper Construction Area"
icon_state = "yellow"
+ ambientsounds = ENGINEERING_SOUNDS
/area/mining_construction
name = "Auxillary Base Construction"
@@ -2035,6 +1926,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
/area/ai_monitored/storage/eva
name = "EVA Storage"
icon_state = "eva"
+ ambientsounds = HIGHSEC_SOUNDS
/area/ai_monitored/storage/secure
name = "Secure Storage"
@@ -2045,7 +1937,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
icon_state = "storage"
/area/turret_protected/
- ambientsounds = list('sound/ambience/ambimalf.ogg')
+ ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg')
/area/turret_protected/ai_upload
name = "\improper AI Upload Chamber"
@@ -2107,16 +1999,14 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
// Telecommunications Satellite
/area/tcommsat
- ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
-
-/area/tcommsat/entrance
- name = "\improper Telecoms Teleporter"
- icon_state = "tcomsatentrance"
+ ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg', 'sound/ambience/ambitech.ogg',\
+ 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambitech3.ogg', 'sound/ambience/ambimystery.ogg')
/area/tcommsat/chamber
name = "\improper Telecoms Central Compartment"
icon_state = "tcomsatcham"
+// These areas are needed for MetaStation's AI sat
/area/turret_protected/tcomsat
name = "\improper Telecoms Satellite"
icon_state = "tcomsatlob"
@@ -2158,6 +2048,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
name = "\improper Strange Location"
icon_state = "away"
report_alerts = FALSE
+ ambientsounds = AWAY_MISSION_SOUNDS
/area/awaymission/example
name = "\improper Strange Station"
@@ -2172,7 +2063,7 @@ GLOBAL_LIST_EMPTY(ghostteleportlocs)
icon_state = "beach"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
requires_power = FALSE
- ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg')
+ ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg', 'sound/ambience/seag2.ogg', 'sound/ambience/seag2.ogg', 'sound/ambience/ambiodd.ogg', 'sound/ambience/ambinice.ogg')
/area/awaymission/undersea
name = "Undersea"
diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm
index 2ca607921ff..8f65ac634f4 100644
--- a/code/game/area/ai_monitored.dm
+++ b/code/game/area/ai_monitored.dm
@@ -3,16 +3,14 @@
var/obj/machinery/camera/motioncamera = null
-/area/ai_monitored/New()
- ..()
+/area/ai_monitored/LateInitialize()
+ . = ..()
// locate and store the motioncamera
- spawn (20) // spawn on a delay to let turfs/objs load
- for(var/obj/machinery/camera/M in src)
- if(M.isMotion())
- motioncamera = M
- M.area_motion = src
- return
- return
+ for(var/obj/machinery/camera/M in src)
+ if(M.isMotion())
+ motioncamera = M
+ M.area_motion = src
+ break
/area/ai_monitored/Entered(atom/movable/O)
..()
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 6ad45532641..da80a6e775c 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -26,7 +26,6 @@
var/power_equip = TRUE
var/power_light = TRUE
var/power_environ = TRUE
- var/music = null
var/used_equip = FALSE
var/used_light = FALSE
var/used_environ = FALSE
@@ -56,12 +55,7 @@
var/global/global_uid = 0
var/uid
- var/list/ambientsounds = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg',\
- 'sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg',\
- 'sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg',\
- 'sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg',\
- 'sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg',\
- 'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
+ var/list/ambientsounds = GENERIC_SOUNDS
var/fast_despawn = FALSE
var/can_get_auto_cryod = TRUE
@@ -379,20 +373,24 @@
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(L && L.client && !L.client.ambience_playing && (L.client.prefs.sound & SOUND_BUZZ)) //split off the white noise from the rest of the ambience because of annoyance complaints - Kluys
- L.client.ambience_playing = 1
- L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ)
+ L.client.ambience_playing = TRUE
+ SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = TRUE, wait = FALSE, volume = 35, channel = CHANNEL_BUZZ))
else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ))
- L.client.ambience_playing = 0
+ L.client.ambience_playing = FALSE
if(prob(35) && L && L.client && (L.client.prefs.sound & SOUND_AMBIENCE))
var/sound = pick(ambientsounds)
if(!L.client.played)
- L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)
- L.client.played = 1
- spawn(600) //ewww - this is very very bad
- if(L && L.client)
- L.client.played = 0
+ SEND_SOUND(L, sound(sound, repeat = FALSE, wait = FALSE, volume = 25, channel = CHANNEL_AMBIENCE))
+ L.client.played = TRUE
+ addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600)
+
+/**
+ * Reset the played var to false on the client
+ */
+/client/proc/ResetAmbiencePlayed()
+ played = FALSE
/area/proc/gravitychange(var/gravitystate = 0, var/area/A)
A.has_gravity = gravitystate
diff --git a/code/game/area/areas/depot-areas.dm b/code/game/area/areas/depot-areas.dm
index 7a7c934df35..4a6606d836e 100644
--- a/code/game/area/areas/depot-areas.dm
+++ b/code/game/area/areas/depot-areas.dm
@@ -216,7 +216,8 @@
if(!silent)
announce_here("Depot Code BLUE", reason)
var/list/possible_bot_spawns = list()
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "syndi_depot_bot")
possible_bot_spawns |= L
if(possible_bot_spawns.len)
@@ -248,7 +249,8 @@
comms_online = TRUE
if(comms_online)
spawn(0)
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(prob(50))
if(L.name == "syndi_depot_backup")
var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/S = new /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space(get_turf(L))
@@ -290,7 +292,7 @@
if(!reactor.has_overloaded)
reactor.overload(containment_failure)
else
- log_debug("Depot: [src] called activate_self_destruct with no reactor.");
+ log_debug("Depot: [src] called activate_self_destruct with no reactor.")
message_admins("Syndicate Depot lacks reactor to initiate self-destruct. Must be destroyed manually.")
updateicon()
@@ -344,7 +346,8 @@
/area/syndicate_depot/core/proc/shields_up()
if(shield_list.len)
return
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "syndi_depot_shield")
var/obj/machinery/shieldwall/syndicate/S = new /obj/machinery/shieldwall/syndicate(L.loc)
shield_list += S.UID()
diff --git a/code/game/area/areas/mining.dm b/code/game/area/areas/mining.dm
index 0b07fffda5e..b621bade493 100644
--- a/code/game/area/areas/mining.dm
+++ b/code/game/area/areas/mining.dm
@@ -7,7 +7,6 @@
/area/mine/explored
name = "Mine"
icon_state = "explored"
- music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
@@ -15,7 +14,7 @@
power_equip = FALSE
power_light = FALSE
outdoors = TRUE
- ambientsounds = list('sound/ambience/ambimine.ogg')
+ ambientsounds = MINING_SOUNDS
flags = NONE
/area/mine/dangerous/explored/golem
@@ -24,7 +23,6 @@
/area/mine/unexplored
name = "Mine"
icon_state = "unexplored"
- music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
@@ -32,7 +30,7 @@
power_equip = FALSE
power_light = FALSE
outdoors = TRUE
- ambientsounds = list('sound/ambience/ambimine.ogg')
+ ambientsounds = MINING_SOUNDS
flags = NONE
/area/mine/lobby
@@ -80,6 +78,7 @@
/area/mine/laborcamp/security
name = "Labor Camp Security"
icon_state = "security"
+ ambientsounds = HIGHSEC_SOUNDS
/area/mine/podbay
name = "Mining Podbay"
@@ -95,26 +94,24 @@
/area/lavaland/surface
name = "Lavaland"
icon_state = "explored"
- music = null
always_unpowered = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
requires_power = TRUE
- ambientsounds = list('sound/ambience/ambilava.ogg')
+ ambientsounds = MINING_SOUNDS
/area/lavaland/underground
name = "Lavaland Caves"
icon_state = "unexplored"
- music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
- ambientsounds = list('sound/ambience/ambilava.ogg')
+ ambientsounds = MINING_SOUNDS
/area/lavaland/surface/outdoors
name = "Lavaland Wastes"
diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm
index 5baf1fe315e..53544d8643b 100644
--- a/code/game/area/areas/ruins/lavaland.dm
+++ b/code/game/area/areas/ruins/lavaland.dm
@@ -5,6 +5,7 @@
/area/ruin/powered/clownplanet
icon_state = "dk_yellow"
+ ambientsounds = list('sound/music/clown.ogg')
/area/ruin/powered/animal_hospital
icon_state = "dk_yellow"
@@ -38,7 +39,7 @@
/area/ruin/unpowered/syndicate_lava_base
name = "Secret Base"
icon_state = "dk_yellow"
- ambientsounds = list('sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg')
+ ambientsounds = HIGHSEC_SOUNDS
report_alerts = FALSE
hide_attacklogs = TRUE
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 1cb0ee3baad..776a2bccd12 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -14,21 +14,18 @@
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
var/simulated = TRUE //filter for actions - used by lighting overlays
var/atom_say_verb = "says"
- var/dont_save = 0 // For atoms that are temporary by necessity - like lighting overlays
-
+ var/bubble_icon = "default" ///what icon the mob uses for speechbubbles
+ var/dont_save = FALSE // For atoms that are temporary by necessity - like lighting overlays
///Chemistry.
var/container_type = NONE
var/datum/reagents/reagents = null
//This atom's HUD (med/sec, etc) images. Associative list.
- var/list/image/hud_list = list()
+ var/list/image/hud_list
//HUD images that this atom can provide.
var/list/hud_possible
- ///Chemistry.
-
-
//Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
@@ -38,9 +35,9 @@
//Detective Work, used for allowing a given atom to leave its fibers on stuff. Allowed by default
var/can_leave_fibers = TRUE
- var/allow_spin = 1 //Set this to 1 for a _target_ that is being thrown at; if an atom has this set to 1 then atoms thrown AT it will not spin; currently used for the singularity. -Fox
+ var/allow_spin = TRUE //Set this to 1 for a _target_ that is being thrown at; if an atom has this set to 1 then atoms thrown AT it will not spin; currently used for the singularity. -Fox
- var/admin_spawned = 0 //was this spawned by an admin? used for stat tracking stuff.
+ var/admin_spawned = FALSE //was this spawned by an admin? used for stat tracking stuff.
var/initialized = FALSE
@@ -67,7 +64,6 @@
// we were deleted
return
-
//Called after New if the map is being loaded. mapload = TRUE
//Called from base of New if the map is not being loaded. mapload = FALSE
//This base must be called or derivatives must set initialized to TRUE
@@ -101,7 +97,6 @@
return INITIALIZE_HINT_NORMAL
-
//called if Initialize returns INITIALIZE_HINT_LATELOAD
/atom/proc/LateInitialize()
return
@@ -114,34 +109,34 @@
return
/atom/proc/onCentcom()
+ . = FALSE
var/turf/T = get_turf(src)
if(!T)
- return 0
+ return
if(!is_admin_level(T.z))//if not, don't bother
- return 0
+ return
//check for centcomm shuttles
for(var/centcom_shuttle in list("emergency", "pod1", "pod2", "pod3", "pod4", "ferry"))
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(centcom_shuttle)
if(T in M.areaInstance)
- return 1
+ return TRUE
//finally check for centcom itself
- return istype(T.loc,/area/centcom)
+ return istype(T.loc, /area/centcom)
/atom/proc/onSyndieBase()
+ . = FALSE
var/turf/T = get_turf(src)
if(!T)
- return 0
+ return
if(!is_admin_level(T.z))//if not, don't bother
- return 0
+ return
if(istype(T.loc, /area/shuttle/syndicate_elite) || istype(T.loc, /area/syndicate_mothership))
- return 1
-
- return 0
+ return TRUE
/atom/Destroy()
if(alternate_appearances)
@@ -164,6 +159,34 @@
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
+/*
+ Sets the atom's pixel locations based on the atom's `dir` variable, and what pixel offset arguments are passed into it
+ If no arguments are supplied, `pixel_x` or `pixel_y` will be set to 0
+ Used primarily for when players attach mountable frames to walls (APC frame, fire alarm frame, etc.)
+*/
+/atom/proc/set_pixel_offsets_from_dir(pixel_north = 0, pixel_south = 0, pixel_east = 0, pixel_west = 0)
+ switch(dir)
+ if(NORTH)
+ pixel_y = pixel_north
+ if(SOUTH)
+ pixel_y = pixel_south
+ if(EAST)
+ pixel_x = pixel_east
+ if(WEST)
+ pixel_x = pixel_west
+ if(NORTHEAST)
+ pixel_y = pixel_north
+ pixel_x = pixel_east
+ if(NORTHWEST)
+ pixel_y = pixel_north
+ pixel_x = pixel_west
+ if(SOUTHEAST)
+ pixel_y = pixel_south
+ pixel_x = pixel_east
+ if(SOUTHWEST)
+ pixel_y = pixel_south
+ pixel_x = pixel_west
+
///Handle melee attack by a mech
/atom/proc/mech_melee_attack(obj/mecha/M)
return
@@ -202,9 +225,7 @@
else
return null
-/atom/proc/check_eye(user as mob)
- if(istype(user, /mob/living/silicon/ai)) // WHYYYY
- return 1
+/atom/proc/check_eye(mob/user)
return
/atom/proc/on_reagent_change()
@@ -219,11 +240,11 @@
/// Is this atom injectable into other atoms
/atom/proc/is_injectable(mob/user, allowmobs = TRUE)
- return reagents && (container_type & (INJECTABLE | REFILLABLE))
+ return reagents && (container_type & (INJECTABLE|REFILLABLE))
/// Can we draw from this atom with an injectable atom
/atom/proc/is_drawable(mob/user, allowmobs = TRUE)
- return reagents && (container_type & (DRAWABLE | DRAINABLE))
+ return reagents && (container_type & (DRAWABLE|DRAINABLE))
/// Can this atoms reagents be refilled
/atom/proc/is_refillable()
@@ -234,12 +255,12 @@
return reagents && (container_type & DRAINABLE)
/atom/proc/CheckExit()
- return 1
+ return TRUE
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
return
-/atom/proc/emp_act(var/severity)
+/atom/proc/emp_act(severity)
return
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
@@ -249,13 +270,13 @@
/atom/proc/in_contents_of(container)//can take class or object instance as argument
if(ispath(container))
if(istype(src.loc, container))
- return 1
+ return TRUE
else if(src in container)
- return 1
- return
+ return TRUE
+ return FALSE
/*
- * atom/proc/search_contents_for(path,list/filter_path=null)
+ * atom/proc/search_contents_for(path, list/filter_path = null)
* Recursevly searches all atom contens (including contents contents and so on).
*
* ARGS: path - search atom contents for atoms of this type
@@ -264,7 +285,7 @@
* RETURNS: list of found atoms
*/
-/atom/proc/search_contents_for(path,list/filter_path=null)
+/atom/proc/search_contents_for(path, list/filter_path = null)
var/list/found = list()
for(var/atom/A in src)
if(istype(A, path))
@@ -276,7 +297,7 @@
if(!pass)
continue
if(A.contents.len)
- found += A.search_contents_for(path,filter_path)
+ found += A.search_contents_for(path, filter_path)
return found
@@ -397,43 +418,58 @@
/atom/proc/get_spooked()
return
-/atom/proc/add_hiddenprint(mob/living/M as mob)
- if(isnull(M)) return
- if(isnull(M.key)) return
+/**
+ Base proc, intended to be overriden.
+
+ This should only be called from one place: inside the slippery component.
+ Called after a human mob slips on this atom.
+
+ If you want the person who slipped to have something special done to them, put it here.
+*/
+/atom/proc/after_slip(mob/living/carbon/human/H)
+ return
+
+/atom/proc/add_hiddenprint(mob/living/M)
+ if(isnull(M))
+ return
+ if(isnull(M.key))
+ return
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(!istype(H.dna, /datum/dna))
- return 0
+ return FALSE
if(H.gloves)
if(fingerprintslast != H.ckey)
//Add the list if it does not exist.
if(!fingerprintshidden)
fingerprintshidden = list()
- fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
+ fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []", H.real_name, H.key)
fingerprintslast = H.ckey
- return 0
+ return FALSE
if(!fingerprints)
if(fingerprintslast != H.ckey)
//Add the list if it does not exist.
if(!fingerprintshidden)
fingerprintshidden = list()
- fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key)
+ fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []", H.real_name, H.key)
fingerprintslast = H.ckey
- return 1
+ return TRUE
else
if(fingerprintslast != M.ckey)
//Add the list if it does not exist.
if(!fingerprintshidden)
fingerprintshidden = list()
- fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key)
+ fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []", M.real_name, M.key)
fingerprintslast = M.ckey
return
//Set ignoregloves to add prints irrespective of the mob having gloves on.
-/atom/proc/add_fingerprint(mob/living/M as mob, ignoregloves = 0)
- if(isnull(M)) return
- if(isnull(M.key)) return
+/atom/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
+ if(isnull(M))
+ return
+ if(isnull(M.key))
+ return
if(ishuman(M))
//Add the list if it does not exist.
if(!fingerprintshidden)
@@ -447,7 +483,7 @@
if(fingerprintslast != M.key)
fingerprintshidden += "(Has no fingerprints) Real name: [M.real_name], Key: [M.key]"
fingerprintslast = M.key
- return 0 //Now, lets get to the dirty work.
+ return FALSE //Now, lets get to the dirty work.
//First, make sure their DNA makes sense.
var/mob/living/carbon/human/H = M
if(!istype(H.dna, /datum/dna) || !H.dna.uni_identity || (length(H.dna.uni_identity) != 32))
@@ -460,20 +496,20 @@
if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves
if(G.transfer_prints)
- ignoregloves = 1
+ ignoregloves = TRUE
//Now, deal with gloves.
if(!ignoregloves)
if(H.gloves && H.gloves != src)
if(fingerprintslast != H.ckey)
- fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key)
+ fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []", time_stamp(), H.real_name, H.key)
fingerprintslast = H.ckey
H.gloves.add_fingerprint(M)
- return 0
+ return FALSE
//More adminstuffz
if(fingerprintslast != H.ckey)
- fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key)
+ fingerprintshidden += text("\[[]\]Real name: [], Key: []", time_stamp(), H.real_name, H.key)
fingerprintslast = H.ckey
//Make the list if it does not exist.
@@ -486,18 +522,16 @@
// Add the fingerprints
fingerprints[full_print] = full_print
- return 1
+ return TRUE
else
//Smudge up dem prints some
if(fingerprintslast != M.ckey)
- fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key)
+ fingerprintshidden += text("\[[]\]Real name: [], Key: []", time_stamp(), M.real_name, M.key)
fingerprintslast = M.ckey
return
-
-/atom/proc/transfer_fingerprints_to(var/atom/A)
-
+/atom/proc/transfer_fingerprints_to(atom/A)
// Make sure everything are lists.
if(!islist(A.fingerprints))
A.fingerprints = list()
@@ -544,7 +578,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/transfer_mob_blood_dna(mob/living/L)
var/new_blood_dna = L.get_blood_dna_list()
if(!new_blood_dna)
- return 0
+ return FALSE
return transfer_blood_dna(new_blood_dna)
/obj/effect/decal/cleanable/blood/splatter/transfer_mob_blood_dna(mob/living/L)
@@ -572,14 +606,13 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
var/old_length = blood_DNA.len
blood_DNA |= blood_dna
if(blood_DNA.len > old_length)
- return 1//some new blood DNA was added
-
+ return TRUE//some new blood DNA was added
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
var/list/blood_dna = M.get_blood_dna_list()
if(!blood_dna)
- return 0
+ return FALSE
var/bloodcolor = "#A10808"
var/list/b_data = M.get_blood_data(M.get_blood_id())
if(b_data)
@@ -589,7 +622,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
//to add blood onto something, with blood dna info to include.
/atom/proc/add_blood(list/blood_dna, color)
- return 0
+ return FALSE
/obj/add_blood(list/blood_dna, color)
return transfer_blood_dna(blood_dna)
@@ -597,10 +630,10 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/obj/item/add_blood(list/blood_dna, color)
var/blood_count = !blood_DNA ? 0 : blood_DNA.len
if(!..())
- return 0
+ return FALSE
if(!blood_count)//apply the blood-splatter overlay if it isn't already in there
add_blood_overlay(color)
- return 1 //we applied blood to the item
+ return TRUE //we applied blood to the item
/obj/item/clothing/gloves/add_blood(list/blood_dna, color)
. = ..()
@@ -612,25 +645,25 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
B = new /obj/effect/decal/cleanable/blood/splatter(src)
B.transfer_blood_dna(blood_dna) //give blood info to the blood decal.
B.basecolor = color
- return 1 //we bloodied the floor
+ return TRUE //we bloodied the floor
/mob/living/carbon/human/add_blood(list/blood_dna, color)
if(wear_suit)
wear_suit.add_blood(blood_dna, color)
wear_suit.blood_color = color
- update_inv_wear_suit(1)
+ update_inv_wear_suit()
else if(w_uniform)
w_uniform.add_blood(blood_dna, color)
w_uniform.blood_color = color
- update_inv_w_uniform(1)
+ update_inv_w_uniform()
if(head)
head.add_blood(blood_dna, color)
head.blood_color = color
- update_inv_head(0,0)
+ update_inv_head()
if(glasses)
glasses.add_blood(blood_dna, color)
glasses.blood_color = color
- update_inv_glasses(0)
+ update_inv_glasses()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
G.add_blood(blood_dna, color)
@@ -642,8 +675,8 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
transfer_blood_dna(blood_dna)
verbs += /mob/living/carbon/human/proc/bloody_doodle
- update_inv_gloves(1) //handles bloody hands overlays and updating
- return 1
+ update_inv_gloves() //handles bloody hands overlays and updating
+ return TRUE
/obj/item/proc/add_blood_overlay(color)
if(initial(icon) && initial(icon_state))
@@ -681,7 +714,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
if(.)
transfer_blood = 0
-
/obj/item/clothing/shoes/clean_blood()
..()
bloody_shoes = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0)
@@ -690,23 +722,42 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
var/mob/M = loc
M.update_inv_shoes()
-
-/mob/living/carbon/human/clean_blood()
- if(gloves)
+/mob/living/carbon/human/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
+ if(w_uniform && !(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT))
+ if(w_uniform.clean_blood())
+ update_inv_w_uniform()
+ if(gloves && !(wear_suit && wear_suit.flags_inv & HIDEGLOVES))
if(gloves.clean_blood())
- clean_blood()
- update_inv_gloves()
- gloves.germ_level = 0
- else
- ..() // Clear the Blood_DNA list
- if(bloody_hands)
- bloody_hands = 0
update_inv_gloves()
+ gloves.germ_level = 0
+ clean_hands = FALSE
+ if(shoes && !(wear_suit && wear_suit.flags_inv & HIDESHOES))
+ if(shoes.clean_blood())
+ update_inv_shoes()
+ clean_feet = FALSE
+ if(s_store && !(wear_suit && wear_suit.flags_inv & HIDESUITSTORAGE))
+ if(s_store.clean_blood())
+ update_inv_s_store()
+ if(lip_style && !(head && head.flags_inv & HIDEMASK))
+ lip_style = null
+ update_body()
+ if(glasses && !(wear_mask && wear_mask.flags_inv & HIDEEYES))
+ if(glasses.clean_blood())
+ update_inv_glasses()
+ if(l_ear && !(wear_mask && wear_mask.flags_inv & HIDEEARS))
+ if(l_ear.clean_blood())
+ update_inv_ears()
+ if(r_ear && !(wear_mask && wear_mask.flags_inv & HIDEEARS))
+ if(r_ear.clean_blood())
+ update_inv_ears()
+ if(belt)
+ if(belt.clean_blood())
+ update_inv_belt()
+ ..(clean_hands, clean_mask, clean_feet)
update_icons() //apply the now updated overlays to the mob
-
-/atom/proc/add_vomit_floor(toxvomit = 0, green = FALSE)
- playsound(src, 'sound/effects/splat.ogg', 50, 1)
+/atom/proc/add_vomit_floor(toxvomit = FALSE, green = FALSE)
+ playsound(src, 'sound/effects/splat.ogg', 50, TRUE)
if(!isspaceturf(src))
var/type = green ? /obj/effect/decal/cleanable/vomit/green : /obj/effect/decal/cleanable/vomit
var/vomit_reagent = green ? "green_vomit" : "vomit"
@@ -719,23 +770,24 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
// Make toxins vomit look different
if(toxvomit)
- this.icon_state = "vomittox_[pick(1,4)]"
+ this.icon_state = "vomittox_[pick(1, 4)]"
/atom/proc/get_global_map_pos()
- if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map)) return
+ if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map))
+ return
var/cur_x = null
var/cur_y = null
var/list/y_arr = null
- for(cur_x=1,cur_x<=GLOB.global_map.len,cur_x++)
+ for(cur_x in 1 to GLOB.global_map.len)
y_arr = GLOB.global_map[cur_x]
cur_y = y_arr.Find(src.z)
if(cur_y)
break
// to_chat(world, "X = [cur_x]; Y = [cur_y]")
if(cur_x && cur_y)
- return list("x"=cur_x,"y"=cur_y)
+ return list("x" = cur_x, "y" = cur_y)
else
- return 0
+ return null
// Used to provide overlays when using this atom as a viewing focus
// (cameras, locker tint, etc.)
@@ -748,7 +800,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
return
/atom/proc/checkpass(passflag)
- return pass_flags&passflag
+ return pass_flags & passflag
/atom/proc/isinspace()
if(isspaceturf(get_turf(src)))
@@ -789,9 +841,18 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/atom_say(message)
if(!message)
return
- audible_message("[src] [atom_say_verb], \"[message]\"")
+ var/list/speech_bubble_hearers = list()
+ for(var/mob/M in get_mobs_in_view(7, src))
+ M.show_message("[src] [atom_say_verb], \"[message]\"", 2, null, 1)
+ if(M.client)
+ speech_bubble_hearers += M.client
-/atom/proc/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
+ if(length(speech_bubble_hearers))
+ var/image/I = image('icons/mob/talk.dmi', src, "[bubble_icon][say_test(message)]", FLY_LAYER)
+ I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
+ INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_hearers, 30)
+
+/atom/proc/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
return
/atom/vv_edit_var(var_name, var_value)
@@ -848,7 +909,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
atom_colours[colour_priority] = coloration
update_atom_colour()
-
/*
Removes an instance of colour_type from the atom's atom_colours list
*/
@@ -863,7 +923,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
atom_colours[colour_priority] = null
update_atom_colour()
-
/*
Resets the atom's color to null, and then sets it to the highest priority
colour available
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 6b49962bbac..00009c8eeca 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -1,6 +1,7 @@
/atom/movable
layer = 3
appearance_flags = TILE_BOUND
+ glide_size = 8 // Default, adjusted when mobs move based on their movement delays
var/last_move = null
var/anchored = 0
var/move_resist = MOVE_RESIST_DEFAULT
@@ -43,16 +44,18 @@
/atom/movable/Destroy()
unbuckle_all_mobs(force = TRUE)
+
+ . = ..()
if(loc)
loc.handle_atom_del(src)
for(var/atom/movable/AM in contents)
qdel(AM)
+ LAZYCLEARLIST(client_mobs_in_contents)
loc = null
if(pulledby)
- if(pulledby.pulling == src)
- pulledby.pulling = null
- pulledby = null
- return ..()
+ pulledby.stop_pulling()
+ if(orbiting)
+ stop_orbit()
//Returns an atom's power cell, if it has one. Overload for individual items.
/atom/movable/proc/get_cell()
@@ -131,13 +134,14 @@
/atom/movable/proc/setLoc(var/T, var/teleported=0)
loc = T
-/atom/movable/Move(atom/newloc, direct = 0)
+/atom/movable/Move(atom/newloc, direct = 0, movetime)
if(!loc || !newloc) return 0
var/atom/oldloc = loc
if(loc != newloc)
+ glide_for(movetime)
if(!(direct & (direct - 1))) //Cardinal move
- . = ..()
+ . = ..(newloc, direct) // don't pass up movetime
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
var/first_step_dir
@@ -203,7 +207,7 @@
src.move_speed = world.time - src.l_move_time
src.l_move_time = world.time
- if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct)) //movement failed due to buckled mob
+ if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, movetime)) //movement failed due to buckled mob
. = 0
// Called after a successful Move(). By this point, we've already moved
@@ -216,12 +220,24 @@
update_parallax_contents()
return TRUE
+// Change glide size for the duration of one movement
+/atom/movable/proc/glide_for(movetime)
+ if(movetime)
+ glide_size = world.icon_size/max(DS2TICKS(movetime), 1)
+ spawn(movetime)
+ glide_size = initial(glide_size)
+ else
+ glide_size = initial(glide_size)
+
// Previously known as HasEntered()
// This is automatically called when something enters your square
/atom/movable/Crossed(atom/movable/AM, oldloc)
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
SEND_SIGNAL(AM, COMSIG_CROSSED_MOVABLE, src)
+/atom/movable/Uncrossed(atom/movable/AM)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM)
+
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
if(A && yes)
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
@@ -254,15 +270,8 @@
var/dest_z = (destturf ? destturf.z : null)
if(old_z != dest_z)
onTransitZ(old_z, dest_z)
- if(isturf(destination) && opacity)
- var/turf/new_loc = destination
- new_loc.reconsider_lights()
- if(isturf(old_loc) && opacity)
- old_loc.reconsider_lights()
-
- for(var/datum/light_source/L in light_sources)
- L.source_atom.update_light()
+ Moved(old_loc, NONE)
return 1
@@ -319,7 +328,6 @@
SSspacedrift.processing[src] = src
return 1
-
//called when src is thrown into hit_atom
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
set waitfor = 0
@@ -428,10 +436,10 @@
/atom/movable/proc/water_act(volume, temperature, source, method = REAGENT_TOUCH) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins)
return TRUE
-/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
+/atom/movable/proc/handle_buckled_mob_movement(newloc,direct,movetime)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
- if(!buckled_mob.Move(newloc, direct))
+ if(!buckled_mob.Move(newloc, direct, movetime))
forceMove(buckled_mob.loc)
last_move = buckled_mob.last_move
inertia_dir = last_move
@@ -490,7 +498,7 @@
target.fingerprintshidden += fingerprintshidden
target.fingerprintslast = fingerprintslast
-/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
+/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && (visual_effect_icon || used_item))
do_item_attack_animation(A, visual_effect_icon, used_item)
@@ -498,10 +506,6 @@
return //don't do an animation if attacking self
var/pixel_x_diff = 0
var/pixel_y_diff = 0
- var/final_pixel_y = initial(pixel_y)
- if(end_pixel_y)
- final_pixel_y = end_pixel_y
-
var/direction = get_dir(src, A)
if(direction & NORTH)
pixel_y_diff = 8
@@ -514,7 +518,7 @@
pixel_x_diff = -8
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2)
- animate(pixel_x = initial(pixel_x), pixel_y = final_pixel_y, time = 2)
+ animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, time = 2)
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
var/image/I
@@ -563,3 +567,6 @@
/atom/movable/proc/portal_destroyed(obj/effect/portal/P)
return
+
+/atom/movable/proc/decompile_act(obj/item/matter_decompiler/C, mob/user) // For drones to decompile mobs and objs. See drone for an example.
+ return FALSE
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index aff345d2451..6bd00d286fe 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -135,8 +135,6 @@
return "health-90"
else
return "health-100" //past this point, you're just in trouble
- return "0"
-
///HOOKS
@@ -223,19 +221,28 @@
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
if(R)
switch(R.fields["criminal"])
- if("*Execute*")
+ if(SEC_RECORD_STATUS_EXECUTE)
holder.icon_state = "hudexecute"
return
- if("*Arrest*")
+ if(SEC_RECORD_STATUS_ARREST)
holder.icon_state = "hudwanted"
return
- if("Incarcerated")
+ if(SEC_RECORD_STATUS_SEARCH)
+ holder.icon_state = "hudsearch"
+ return
+ if(SEC_RECORD_STATUS_MONITOR)
+ holder.icon_state = "hudmonitor"
+ return
+ if(SEC_RECORD_STATUS_DEMOTE)
+ holder.icon_state = "huddemote"
+ return
+ if(SEC_RECORD_STATUS_INCARCERATED)
holder.icon_state = "hudprisoner"
return
- if("Parolled")
+ if(SEC_RECORD_STATUS_PAROLLED)
holder.icon_state = "hudparolled"
return
- if("Released")
+ if(SEC_RECORD_STATUS_RELEASED)
holder.icon_state = "hudreleased"
return
holder.icon_state = null
@@ -261,7 +268,6 @@
return "crit"
else
return "dead"
- return "dead"
//Sillycone hooks
/mob/living/silicon/proc/diag_hud_set_health()
@@ -391,7 +397,6 @@
return "max"
else
return "zero"
- return "zero"
/obj/machinery/hydroponics/proc/plant_hud_set_nutrient()
var/image/holder = hud_list[PLANT_NUTRIENT_HUD]
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index ceabae25973..1a92210f570 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -22,17 +22,17 @@ GLOBAL_LIST_EMPTY(bad_blocks)
/datum/dna
// READ-ONLY, GETS OVERWRITTEN
// DO NOT FUCK WITH THESE OR BYOND WILL EAT YOUR FACE
- var/uni_identity="" // Encoded UI
- var/struc_enzymes="" // Encoded SE
- var/unique_enzymes="" // MD5 of player name
+ var/uni_identity = "" // Encoded UI
+ var/struc_enzymes = "" // Encoded SE
+ var/unique_enzymes = "" // MD5 of player name
// Original Encoded SE, for use with Ryetalin
- var/struc_enzymes_original="" // Encoded SE
+ var/struc_enzymes_original = "" // Encoded SE
var/list/SE_original[DNA_SE_LENGTH]
// Internal dirtiness checks
- var/dirtyUI=0
- var/dirtySE=0
+ var/dirtyUI = 0
+ var/dirtySE = 0
// Okay to read, but you're an idiot if you do.
// BLOCK = VALUE
@@ -50,10 +50,10 @@ GLOBAL_LIST_EMPTY(bad_blocks)
// USE THIS WHEN COPYING STUFF OR YOU'LL GET CORRUPTION!
/datum/dna/proc/Clone()
var/datum/dna/new_dna = new()
- new_dna.unique_enzymes=unique_enzymes
- new_dna.struc_enzymes_original=struc_enzymes_original // will make clone's SE the same as the original, do we want this?
+ new_dna.unique_enzymes = unique_enzymes
+ new_dna.struc_enzymes_original = struc_enzymes_original // will make clone's SE the same as the original, do we want this?
new_dna.blood_type = blood_type
- new_dna.real_name=real_name
+ new_dna.real_name = real_name
new_dna.species = new species.type
for(var/b=1;b<=DNA_SE_LENGTH;b++)
new_dna.SE[b]=SE[b]
@@ -68,17 +68,17 @@ GLOBAL_LIST_EMPTY(bad_blocks)
///////////////////////////////////////
// Create random UI.
-/datum/dna/proc/ResetUI(var/defer=0)
+/datum/dna/proc/ResetUI(defer = FALSE)
for(var/i=1,i<=DNA_UI_LENGTH,i++)
switch(i)
if(DNA_UI_SKIN_TONE)
- SetUIValueRange(DNA_UI_SKIN_TONE,rand(1,220),220,1) // Otherwise, it gets fucked
+ SetUIValueRange(DNA_UI_SKIN_TONE, rand(1, 220), 220, 1) // Otherwise, it gets fucked
else
UI[i]=rand(0,4095)
if(!defer)
UpdateUI()
-/datum/dna/proc/ResetUIFrom(var/mob/living/carbon/human/character)
+/datum/dna/proc/ResetUIFrom(mob/living/carbon/human/character)
// INITIALIZE!
ResetUI(1)
// Hair
@@ -135,83 +135,90 @@ GLOBAL_LIST_EMPTY(bad_blocks)
UpdateUI()
// Set a DNA UI block's raw value.
-/datum/dna/proc/SetUIValue(var/block,var/value,var/defer=0)
- if(block<=0) return
- ASSERT(value>0)
- ASSERT(value<=4095)
+/datum/dna/proc/SetUIValue(block, value, defer = FALSE)
+ if(block <= 0)
+ return
+ ASSERT(value > 0)
+ ASSERT(value <= 4095)
UI[block]=value
- dirtyUI=1
+ dirtyUI = 1
if(!defer)
UpdateUI()
// Get a DNA UI block's raw value.
-/datum/dna/proc/GetUIValue(var/block)
- if(block<=0) return 0
+/datum/dna/proc/GetUIValue(block)
+ if(block <= 0)
+ return FALSE
return UI[block]
// Set a DNA UI block's value, given a value and a max possible value.
// Used in hair and facial styles (value being the index and maxvalue being the len of the hairstyle list)
-/datum/dna/proc/SetUIValueRange(var/block,var/value,var/maxvalue,var/defer=0)
- if(block<=0)
+/datum/dna/proc/SetUIValueRange(block, value, maxvalue, defer = FALSE)
+ if(block <= 0)
return
if(value == 0)
value = 1
- ASSERT(maxvalue<=4095)
+ ASSERT(maxvalue <= 4095)
var/range = (4095 / maxvalue)
if(value)
- SetUIValue(block,round(value * range),defer)
+ SetUIValue(block,round(value * range), defer)
// Getter version of above.
-/datum/dna/proc/GetUIValueRange(var/block,var/maxvalue)
- if(block<=0) return 0
+/datum/dna/proc/GetUIValueRange(block, maxvalue)
+ if(block <= 0)
+ return FALSE
var/value = GetUIValue(block)
- return round(1 +(value / 4096)*maxvalue)
+ return round(1 + (value / 4096) * maxvalue)
// Is the UI gene "on" or "off"?
// For UI, this is simply a check of if the value is > 2050.
-/datum/dna/proc/GetUIState(var/block)
- if(block<=0) return
+/datum/dna/proc/GetUIState(block)
+ if(block <= 0)
+ return
return UI[block] > 2050
// Set UI gene "on" (1) or "off" (0)
-/datum/dna/proc/SetUIState(var/block,var/on,var/defer=0)
- if(block<=0) return
+/datum/dna/proc/SetUIState(block, on, defer = FALSE)
+ if(block <= 0)
+ return
var/val
if(on)
- val=rand(2050,4095)
+ val = rand(2050, 4095)
else
- val=rand(1,2049)
- SetUIValue(block,val,defer)
+ val=rand(1, 2049)
+ SetUIValue(block, val, defer)
// Get a hex-encoded UI block.
-/datum/dna/proc/GetUIBlock(var/block)
+/datum/dna/proc/GetUIBlock(block)
return EncodeDNABlock(GetUIValue(block))
// Do not use this unless you absolutely have to.
// Set a block from a hex string. This is inefficient. If you can, use SetUIValue().
// Used in DNA modifiers.
-/datum/dna/proc/SetUIBlock(var/block,var/value,var/defer=0)
- if(block<=0) return
- return SetUIValue(block,hex2num(value),defer)
+/datum/dna/proc/SetUIBlock(block, value, defer = FALSE)
+ if(block <= 0)
+ return
+ return SetUIValue(block, hex2num(value), defer)
// Get a sub-block from a block.
-/datum/dna/proc/GetUISubBlock(var/block,var/subBlock)
- return copytext(GetUIBlock(block),subBlock,subBlock+1)
+/datum/dna/proc/GetUISubBlock(block, subBlock)
+ return copytext(GetUIBlock(block), subBlock, subBlock + 1)
// Do not use this unless you absolutely have to.
// Set a block from a hex string. This is inefficient. If you can, use SetUIValue().
// Used in DNA modifiers.
-/datum/dna/proc/SetUISubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0)
- if(block<=0) return
- var/oldBlock=GetUIBlock(block)
- var/newBlock=""
- for(var/i=1, i<=length(oldBlock), i++)
+/datum/dna/proc/SetUISubBlock(block, subBlock, newSubBlock, defer = FALSE)
+ if(block <= 0)
+ return
+ var/oldBlock = GetUIBlock(block)
+ var/newBlock = ""
+ for(var/i = 1, i <= length(oldBlock), i++)
if(i==subBlock)
- newBlock+=newSubBlock
+ newBlock += newSubBlock
else
- newBlock+=copytext(oldBlock,i,i+1)
- SetUIBlock(block,newBlock,defer)
+ newBlock += copytext(oldBlock, i, i + 1)
+ SetUIBlock(block, newBlock, defer)
///////////////////////////////////////
// STRUCTURAL ENZYMES
@@ -220,126 +227,134 @@ GLOBAL_LIST_EMPTY(bad_blocks)
// "Zeroes out" all of the blocks.
/datum/dna/proc/ResetSE()
for(var/i = 1, i <= DNA_SE_LENGTH, i++)
- SetSEValue(i,rand(1,1024),1)
+ SetSEValue(i, rand(1, 1024), 1)
UpdateSE()
// Set a DNA SE block's raw value.
-/datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0)
+/datum/dna/proc/SetSEValue(block, value, defer = FALSE)
- if(block<=0) return
- ASSERT(value>=0)
- ASSERT(value<=4095)
- SE[block]=value
- dirtySE=1
+ if(block<=0)
+ return
+ ASSERT(value >= 0)
+ ASSERT(value <= 4095)
+ SE[block] = value
+ dirtySE = 1
if(!defer)
UpdateSE()
//testing("SetSEBlock([block],[value],[defer]): [value] -> [GetSEValue(block)]")
// Get a DNA SE block's raw value.
-/datum/dna/proc/GetSEValue(var/block)
- if(block<=0) return 0
+/datum/dna/proc/GetSEValue(block)
+ if(block <= 0)
+ return FALSE
return SE[block]
// Set a DNA SE block's value, given a value and a max possible value.
// Might be used for species?
-/datum/dna/proc/SetSEValueRange(var/block,var/value,var/maxvalue)
- if(block<=0) return
- ASSERT(maxvalue<=4095)
+/datum/dna/proc/SetSEValueRange(block, value, maxvalue)
+ if(block <= 0)
+ return
+ ASSERT(maxvalue <= 4095)
var/range = round(4095 / maxvalue)
if(value)
- SetSEValue(block, value * range - rand(1,range-1))
+ SetSEValue(block, value * range - rand(1, range - 1))
// Getter version of above.
-/datum/dna/proc/GetSEValueRange(var/block,var/maxvalue)
- if(block<=0) return 0
+/datum/dna/proc/GetSEValueRange(block, maxvalue)
+ if(block <= 0)
+ return FALSE
var/value = GetSEValue(block)
- return round(1 +(value / 4096)*maxvalue)
+ return round(1 + (value / 4096) * maxvalue)
// Is the block "on" (1) or "off" (0)? (Un-assigned genes are always off.)
-/datum/dna/proc/GetSEState(var/block)
- if(block<=0) return 0
- var/list/BOUNDS=GetDNABounds(block)
- var/value=GetSEValue(block)
+/datum/dna/proc/GetSEState(block)
+ if(block <= 0)
+ return FALSE
+ var/list/BOUNDS = GetDNABounds(block)
+ var/value = GetSEValue(block)
return (value >= BOUNDS[DNA_ON_LOWERBOUND])
// Set a block "on" or "off".
-/datum/dna/proc/SetSEState(var/block,var/on,var/defer=0)
- if(block<=0) return
+/datum/dna/proc/SetSEState(block, on, defer = FALSE)
+ if(block <= 0)
+ return
var/list/BOUNDS=GetDNABounds(block)
var/val
if(on)
- val=rand(BOUNDS[DNA_ON_LOWERBOUND],BOUNDS[DNA_ON_UPPERBOUND])
+ val = rand(BOUNDS[DNA_ON_LOWERBOUND], BOUNDS[DNA_ON_UPPERBOUND])
else
- val=rand(1,BOUNDS[DNA_OFF_UPPERBOUND])
- SetSEValue(block,val,defer)
+ val = rand(1, BOUNDS[DNA_OFF_UPPERBOUND])
+ SetSEValue(block, val, defer)
// Get hex-encoded SE block.
-/datum/dna/proc/GetSEBlock(var/block)
+/datum/dna/proc/GetSEBlock(block)
return EncodeDNABlock(GetSEValue(block))
// Do not use this unless you absolutely have to.
// Set a block from a hex string. This is inefficient. If you can, use SetUIValue().
// Used in DNA modifiers.
-/datum/dna/proc/SetSEBlock(var/block,var/value,var/defer=0)
- if(block<=0) return
+/datum/dna/proc/SetSEBlock(block, value, defer = FALSE)
+ if(block <= 0)
+ return
var/nval=hex2num(value)
//testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]")
- return SetSEValue(block,nval,defer)
+ return SetSEValue(block, nval, defer)
-/datum/dna/proc/GetSESubBlock(var/block,var/subBlock)
- return copytext(GetSEBlock(block),subBlock,subBlock+1)
+/datum/dna/proc/GetSESubBlock(block, subBlock)
+ return copytext(GetSEBlock(block), subBlock, subBlock + 1)
// Do not use this unless you absolutely have to.
// Set a sub-block from a hex character. This is inefficient. If you can, use SetUIValue().
// Used in DNA modifiers.
-/datum/dna/proc/SetSESubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0)
- if(block<=0) return
+/datum/dna/proc/SetSESubBlock(block, subBlock, newSubBlock, defer = FALSE)
+ if(block <= 0)
+ return
var/oldBlock=GetSEBlock(block)
- var/newBlock=""
- for(var/i=1, i<=length(oldBlock), i++)
+ var/newBlock = ""
+ for(var/i = 1, i <= length(oldBlock), i++)
if(i==subBlock)
newBlock+=newSubBlock
else
- newBlock+=copytext(oldBlock,i,i+1)
+ newBlock += copytext(oldBlock, i, i + 1)
//testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]")
- SetSEBlock(block,newBlock,defer)
+ SetSEBlock(block, newBlock, defer)
-/proc/EncodeDNABlock(var/value)
- return add_zero2(num2hex(value,1), 3)
+/proc/EncodeDNABlock(value)
+ return add_zero2(num2hex(value, 1), 3)
/datum/dna/proc/UpdateUI()
- src.uni_identity=""
+ uni_identity = ""
for(var/block in UI)
uni_identity += EncodeDNABlock(block)
//testing("New UI: [uni_identity]")
- dirtyUI=0
+ dirtyUI = 0
/datum/dna/proc/UpdateSE()
//var/oldse=struc_enzymes
- struc_enzymes=""
+ struc_enzymes = ""
for(var/block in SE)
struc_enzymes += EncodeDNABlock(block)
//testing("Old SE: [oldse]")
//testing("New SE: [struc_enzymes]")
- dirtySE=0
+ dirtySE = 0
// BACK-COMPAT!
// Just checks our character has all the crap it needs.
-/datum/dna/proc/check_integrity(var/mob/living/carbon/human/character)
+/datum/dna/proc/check_integrity(mob/living/carbon/human/character)
if(character)
if(UI.len != DNA_UI_LENGTH)
ResetUIFrom(character)
- if(length(struc_enzymes)!= 3*DNA_SE_LENGTH)
+ if(length(struc_enzymes)!= 3 * DNA_SE_LENGTH)
ResetSE()
if(length(unique_enzymes) != 32)
unique_enzymes = md5(character.real_name)
else
- if(length(uni_identity) != 3*DNA_UI_LENGTH)
+ if(length(uni_identity) != 3 * DNA_UI_LENGTH)
uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4"
- if(length(struc_enzymes)!= 3*DNA_SE_LENGTH)
+ if(length(struc_enzymes)!= 3 * DNA_SE_LENGTH)
struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6"
// BACK-COMPAT!
diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm
index 0091745c518..16eee549bf2 100644
--- a/code/game/dna/dna2_domutcheck.dm
+++ b/code/game/dna/dna2_domutcheck.dm
@@ -3,7 +3,7 @@
// M: Mob to mess with
// connected: Machine we're in, type unchecked so I doubt it's used beyond monkeying
// flags: See below, bitfield.
-/proc/domutcheck(var/mob/living/M, var/connected=null, var/flags=0)
+/proc/domutcheck(mob/living/M, connected = null, flags = 0)
for(var/datum/dna/gene/gene in GLOB.dna_genes)
if(!M || !M.dna)
return
@@ -13,7 +13,7 @@
domutation(gene, M, connected, flags)
// Use this to force a mut check on a single gene!
-/proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0)
+/proc/genemutcheck(mob/living/M, block, connected = null, flags = 0)
if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure.
var/mob/living/carbon/human/H = M
if(NO_DNA in H.dna.species.species_traits)
@@ -27,9 +27,9 @@
domutation(gene, M, connected, flags)
-/proc/domutation(var/datum/dna/gene/gene, var/mob/living/M, var/connected=null, var/flags=0)
+/proc/domutation(datum/dna/gene/gene, mob/living/M, connected = null, flags = 0)
if(!gene || !istype(gene))
- return 0
+ return FALSE
// Current state
var/gene_active = M.dna.GetSEState(gene.block)
@@ -37,7 +37,7 @@
// Sanity checks, don't skip.
if(!gene.can_activate(M,flags) && gene_active)
//testing("[M] - Failed to activate [gene.name] (can_activate fail).")
- return 0
+ return FALSE
var/defaultgenes // Do not mutate inherent species abilities
if(ishuman(M))
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 1857848c2c9..435133a3796 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -9,58 +9,61 @@
t = "0[t]"
temp1 = t
if(length(t) > u)
- temp1 = copytext(t,2,u+1)
+ temp1 = copytext(t, 2, u + 1)
return temp1
// DNA Gene activation boundaries, see dna2.dm.
// Returns a list object with 4 numbers.
-/proc/GetDNABounds(var/block)
- var/list/BOUNDS=GLOB.dna_activity_bounds[block]
+/proc/GetDNABounds(block)
+ var/list/BOUNDS = GLOB.dna_activity_bounds[block]
if(!istype(BOUNDS))
return DNA_DEFAULT_BOUNDS
return BOUNDS
// Give Random Bad Mutation to M
-/proc/randmutb(var/mob/living/M)
- if(!M || !M.dna) return
+/proc/randmutb(mob/living/M)
+ if(!M || !M.dna)
+ return
M.dna.check_integrity()
var/block = pick(GLOB.bad_blocks)
M.dna.SetSEState(block, 1)
// Give Random Good Mutation to M
-/proc/randmutg(var/mob/living/M)
- if(!M || !M.dna) return
+/proc/randmutg(mob/living/M)
+ if(!M || !M.dna)
+ return
M.dna.check_integrity()
var/block = pick(GLOB.good_blocks)
M.dna.SetSEState(block, 1)
// Random Appearance Mutation
-/proc/randmuti(var/mob/living/M)
- if(!M || !M.dna) return
+/proc/randmuti(mob/living/M)
+ if(!M || !M.dna)
+ return
M.dna.check_integrity()
- M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095))
+ M.dna.SetUIValue(rand(1, DNA_UI_LENGTH), rand(1, 4095))
// Scramble UI or SE.
-/proc/scramble(var/UI, var/mob/M, var/prob)
- if(!M || !M.dna) return
+/proc/scramble(UI, mob/M, prob)
+ if(!M || !M.dna)
+ return
M.dna.check_integrity()
if(UI)
- for(var/i = 1, i <= DNA_UI_LENGTH-1, i++)
+ for(var/i = 1, i <= DNA_UI_LENGTH - 1, i++)
if(prob(prob))
- M.dna.SetUIValue(i,rand(1,4095),1)
+ M.dna.SetUIValue(i, rand(1, 4095), 1)
M.dna.UpdateUI()
M.UpdateAppearance()
else
- for(var/i = 1, i <= DNA_SE_LENGTH-1, i++)
+ for(var/i = 1, i <= DNA_SE_LENGTH - 1, i++)
if(prob(prob))
- M.dna.SetSEValue(i,rand(1,4095),1)
+ M.dna.SetSEValue(i, rand(1, 4095), 1)
M.dna.UpdateSE()
domutcheck(M, null)
- return
// I haven't yet figured out what the fuck this is supposed to do.
-/proc/miniscramble(input,rs,rd)
+/proc/miniscramble(input, rs, rd)
var/output
output = null
if(input == "C" || input == "D" || input == "E" || input == "F")
@@ -79,7 +82,7 @@
// input: YOUR TARGET
// rs: RAD STRENGTH
// rd: DURATION
-/proc/miniscrambletarget(input,rs,rd)
+/proc/miniscrambletarget(input, rs, rd)
var/output = null
switch(input)
if("0")
@@ -124,11 +127,11 @@
// Use mob.UpdateAppearance() instead.
// Simpler. Don't specify UI in order for the mob to use its own.
-/mob/proc/UpdateAppearance(var/list/UI=null)
- if(istype(src, /mob/living/carbon/human))
+/mob/proc/UpdateAppearance(list/UI = null)
+ if(istype(src, /mob/living/carbon/human)) // WHY?!
if(UI!=null)
- src.dna.UI=UI
- src.dna.UpdateUI()
+ dna.UI = UI
+ dna.UpdateUI()
dna.check_integrity()
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
@@ -169,9 +172,9 @@
H.regenerate_icons()
- return 1
+ return TRUE
else
- return 0
+ return FALSE
/*
ORGAN WRITING PROCS
@@ -219,9 +222,9 @@
// In absence of eyes, possibly randomize the eye color DNA?
return
- SetUIValueRange(DNA_UI_EYES_R, color2R(eyes_organ.eye_colour), 255, 1)
- SetUIValueRange(DNA_UI_EYES_G, color2G(eyes_organ.eye_colour), 255, 1)
- SetUIValueRange(DNA_UI_EYES_B, color2B(eyes_organ.eye_colour), 255, 1)
+ SetUIValueRange(DNA_UI_EYES_R, color2R(eyes_organ.eye_colour), 255, 1)
+ SetUIValueRange(DNA_UI_EYES_G, color2G(eyes_organ.eye_colour), 255, 1)
+ SetUIValueRange(DNA_UI_EYES_B, color2B(eyes_organ.eye_colour), 255, 1)
/datum/dna/proc/head_traits_to_dna(obj/item/organ/external/head/head_organ)
if(!head_organ)
@@ -241,26 +244,26 @@
head_organ.ha_style = "None"
var/headacc = GLOB.head_accessory_styles_list.Find(head_organ.ha_style)
- SetUIValueRange(DNA_UI_HAIR_R, color2R(head_organ.hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR_G, color2G(head_organ.hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR_B, color2B(head_organ.hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_R, color2R(head_organ.hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_G, color2G(head_organ.hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_B, color2B(head_organ.hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_R, color2R(head_organ.sec_hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_G, color2G(head_organ.sec_hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_B, color2B(head_organ.sec_hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_R, color2R(head_organ.sec_hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_G, color2G(head_organ.sec_hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_B, color2B(head_organ.sec_hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD_R, color2R(head_organ.facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD_G, color2G(head_organ.facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD_B, color2B(head_organ.facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_R, color2R(head_organ.facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_G, color2G(head_organ.facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_B, color2B(head_organ.facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_R, color2R(head_organ.sec_facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_G, color2G(head_organ.sec_facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_B, color2B(head_organ.sec_facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_R, color2R(head_organ.sec_facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_G, color2G(head_organ.sec_facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_B, color2B(head_organ.sec_facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_HACC_R, color2R(head_organ.headacc_colour), 255, 1)
- SetUIValueRange(DNA_UI_HACC_G, color2G(head_organ.headacc_colour), 255, 1)
- SetUIValueRange(DNA_UI_HACC_B, color2B(head_organ.headacc_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HACC_R, color2R(head_organ.headacc_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HACC_G, color2G(head_organ.headacc_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HACC_B, color2B(head_organ.headacc_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_full_list.len, 1)
- SetUIValueRange(DNA_UI_BEARD_STYLE, beard, GLOB.facial_hair_styles_list.len, 1)
- SetUIValueRange(DNA_UI_HACC_STYLE, headacc, GLOB.head_accessory_styles_list.len, 1)
+ SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_full_list.len, 1)
+ SetUIValueRange(DNA_UI_BEARD_STYLE, beard, GLOB.facial_hair_styles_list.len, 1)
+ SetUIValueRange(DNA_UI_HACC_STYLE, headacc, GLOB.head_accessory_styles_list.len, 1)
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index de42b5b253f..fb0ccff32cb 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -10,15 +10,15 @@
//list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0),
/datum/dna2/record
var/datum/dna/dna = null
- var/types=0
- var/name="Empty"
+ var/types = 0
+ var/name = "Empty"
// Stuff for cloners
- var/id=null
- var/implant=null
- var/ckey=null
- var/mind=null
- var/languages=null
+ var/id = null
+ var/implant = null
+ var/ckey = null
+ var/mind = null
+ var/languages = null
/datum/dna2/record/proc/GetData()
var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0)
@@ -28,7 +28,7 @@
ser["data"] = dna.SE
else
ser["data"] = dna.UI
- ser["owner"] = src.dna.real_name
+ ser["owner"] = dna.real_name
ser["label"] = name
if(types & DNA2_BUF_UI)
ser["type"] = "ui"
@@ -54,13 +54,13 @@
desc = "It scans DNA structures."
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "scanner_open"
- density = 1
- anchored = 1.0
+ density = TRUE
+ anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 50
active_power_usage = 300
interact_offline = 1
- var/locked = 0
+ var/locked = FALSE
var/mob/living/carbon/occupant = null
var/obj/item/reagent_containers/glass/beaker = null
var/opened = 0
@@ -106,27 +106,27 @@
/obj/machinery/dna_scannernew/AllowDrop()
return FALSE
-/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
+/obj/machinery/dna_scannernew/relaymove(mob/user)
if(user.stat)
return
- src.go_out()
- return
+ go_out()
/obj/machinery/dna_scannernew/verb/eject()
set src in oview(1)
set category = null
set name = "Eject DNA Scanner"
- if(usr.stat != 0)
+ if(usr.incapacitated())
return
-
- eject_occupant()
-
+ eject_occupant(usr)
add_fingerprint(usr)
- return
-/obj/machinery/dna_scannernew/proc/eject_occupant()
- src.go_out()
+/obj/machinery/dna_scannernew/Destroy()
+ eject_occupant(null, TRUE)
+ return ..()
+
+/obj/machinery/dna_scannernew/proc/eject_occupant(user, force)
+ go_out(user, force)
for(var/obj/O in src)
if(!istype(O,/obj/item/circuitboard/clonescanner) && \
!istype(O,/obj/item/stock_parts) && \
@@ -142,14 +142,12 @@
set category = null
set name = "Enter DNA Scanner"
- if(usr.stat != 0)
- return
- if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other
+ if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
return
if(!ishuman(usr)) //Make sure they're a mob that has dna
to_chat(usr, "Try as you might, you can not climb up into the [src].")
return
- if(src.occupant)
+ if(occupant)
to_chat(usr, "The [src] is already occupied!")
return
if(usr.abiotic())
@@ -160,12 +158,11 @@
return
usr.stop_pulling()
usr.forceMove(src)
- src.occupant = usr
- src.icon_state = "scanner_occupied"
- src.add_fingerprint(usr)
- return
+ occupant = usr
+ icon_state = "scanner_occupied"
+ add_fingerprint(usr)
-/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
+/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O, mob/user)
if(!istype(O))
return
if(O.loc == user) //no you can't pull things out of your ass
@@ -204,27 +201,27 @@
if(user.pulling == L)
user.stop_pulling()
-/obj/machinery/dna_scannernew/attackby(var/obj/item/item as obj, var/mob/user as mob, params)
- if(exchange_parts(user, item))
+/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
+ if(exchange_parts(user, I))
return
- else if(istype(item, /obj/item/reagent_containers/glass))
+ else if(istype(I, /obj/item/reagent_containers/glass))
if(beaker)
to_chat(user, "A beaker is already loaded into the machine.")
return
if(!user.drop_item())
- to_chat(user, "\The [item] is stuck to you!")
+ to_chat(user, "\The [I] is stuck to you!")
return
- beaker = item
- item.forceMove(src)
- user.visible_message("[user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!")
+ beaker = I
+ I.forceMove(src)
+ user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!")
return
- if(istype(item, /obj/item/grab))
- var/obj/item/grab/G = item
+ if(istype(I, /obj/item/grab))
+ var/obj/item/grab/G = I
if(!ismob(G.affecting))
return
- if(src.occupant)
+ if(occupant)
to_chat(user, "The scanner is already occupied!")
return
if(G.affecting.abiotic())
@@ -237,7 +234,7 @@
to_chat(usr, "Close the maintenance panel first.")
return
put_in(G.affecting)
- src.add_fingerprint(user)
+ add_fingerprint(user)
qdel(G)
return
return ..()
@@ -245,7 +242,7 @@
/obj/machinery/dna_scannernew/crowbar_act(mob/user, obj/item/I)
if(default_deconstruction_crowbar(user, I))
for(var/obj/thing in contents) // in case there is something in the scanner
- thing.forceMove(src.loc)
+ thing.forceMove(loc)
/obj/machinery/dna_scannernew/screwdriver_act(mob/user, obj/item/I)
if(occupant)
@@ -254,15 +251,15 @@
if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I))
return TRUE
-/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
+/obj/machinery/dna_scannernew/relaymove(mob/user)
if(user.incapacitated())
- return 0 //maybe they should be able to get out with cuffs, but whatever
+ return FALSE //maybe they should be able to get out with cuffs, but whatever
go_out()
-/obj/machinery/dna_scannernew/proc/put_in(var/mob/M)
+/obj/machinery/dna_scannernew/proc/put_in(mob/M)
M.forceMove(src)
- src.occupant = M
- src.icon_state = "scanner_occupied"
+ occupant = M
+ icon_state = "scanner_occupied"
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
@@ -271,20 +268,19 @@
|| locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
occupant.notify_ghost_cloning(source = src)
- return
-/obj/machinery/dna_scannernew/proc/go_out()
- if(!src.occupant)
- to_chat(usr, "The scanner is empty!")
+/obj/machinery/dna_scannernew/proc/go_out(mob/user, force)
+ if(!occupant)
+ if(user)
+ to_chat(user, "The scanner is empty!")
return
-
- if(src.locked)
- to_chat(usr, "The scanner is locked!")
+ if(locked && !force)
+ if(user)
+ to_chat(user, "The scanner is locked!")
return
-
- src.occupant.forceMove(src.loc)
- src.occupant = null
- src.icon_state = "scanner_open"
+ occupant.forceMove(loc)
+ occupant = null
+ icon_state = "scanner_open"
/obj/machinery/dna_scannernew/ex_act(severity)
if(occupant)
@@ -301,18 +297,17 @@
// Checks if occupants can be irradiated/mutated - prevents exploits where wearing full rad protection would still let you gain mutations
/obj/machinery/dna_scannernew/proc/radiation_check()
if(!occupant)
- return 1
+ return TRUE
if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
if(NO_DNA in H.dna.species.species_traits)
- return 1
+ return TRUE
var/radiation_protection = occupant.run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm.")
if(radiation_protection > NEGATE_MUTATION_THRESHOLD)
- return 1
-
- return 0
+ return TRUE
+ return FALSE
/obj/machinery/computer/scan_consolenew
name = "\improper DNA Modifier access console"
@@ -320,7 +315,7 @@
icon = 'icons/obj/computer.dmi'
icon_screen = "dna"
icon_keyboard = "med_key"
- density = 1
+ density = TRUE
circuit = /obj/item/circuitboard/scan_consolenew
var/selected_ui_block = 1.0
var/selected_ui_subblock = 1.0
@@ -332,22 +327,22 @@
var/radiation_intensity = 1.0
var/list/datum/dna2/record/buffers[3]
var/irradiating = 0
- var/injector_ready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
+ var/injector_ready = FALSE //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/disk/data/disk = null
var/selected_menu_key = null
- anchored = 1
+ anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 400
- var/waiting_for_user_input=0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X
+ var/waiting_for_user_input = 0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X
-/obj/machinery/computer/scan_consolenew/attackby(obj/item/I as obj, mob/user as mob, params)
+/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/disk/data)) //INSERT SOME diskS
- if(!src.disk)
+ if(!disk)
user.drop_item()
I.forceMove(src)
- src.disk = I
+ disk = I
to_chat(user, "You insert [I].")
SSnanoui.update_uis(src) // update all UIs attached to src()
return
@@ -364,39 +359,30 @@
if(!isnull(connected))
break
spawn(250)
- src.injector_ready = 1
- return
- return
+ injector_ready = TRUE
-/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(var/list/buffer)
+/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(list/buffer)
var/list/arr = list()
for(var/i = 1, i <= buffer.len, i++)
arr += "[i]:[EncodeDNABlock(buffer[i])]"
return arr
-/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/dnainjector/I, var/blk, var/datum/dna2/record/buffer)
+/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(obj/item/dnainjector/I, blk, datum/dna2/record/buffer)
var/pos = findtext(blk,":")
- if(!pos) return 0
+ if(!pos)
+ return FALSE
var/id = text2num(copytext(blk,1,pos))
- if(!id) return 0
+ if(!id)
+ return FALSE
I.block = id
I.buf = buffer
- return 1
+ return TRUE
-/*
-/obj/machinery/computer/scan_consolenew/process() //not really used right now
- if(stat & (NOPOWER|BROKEN))
- return
- if(!( src.status )) //remove this
- return
- return
-*/
-
-/obj/machinery/computer/scan_consolenew/attack_ai(user as mob)
- src.add_hiddenprint(user)
+/obj/machinery/computer/scan_consolenew/attack_ai(mob/user)
+ add_hiddenprint(user)
attack_hand(user)
-/obj/machinery/computer/scan_consolenew/attack_hand(user as mob)
+/obj/machinery/computer/scan_consolenew/attack_hand(mob/user)
if(isnull(connected))
for(dir in list(NORTH,EAST,SOUTH,WEST))
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
@@ -423,7 +409,7 @@
*
* @return nothing
*/
-/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
if(user == connected.occupant)
return
@@ -441,7 +427,7 @@
/obj/machinery/computer/scan_consolenew/ui_data(mob/user, datum/topic_state/state)
var/data[0]
data["selectedMenuKey"] = selected_menu_key
- data["locked"] = src.connected.locked
+ data["locked"] = connected.locked
data["hasOccupant"] = connected.occupant ? 1 : 0
data["isInjectorReady"] = injector_ready
@@ -460,7 +446,7 @@
data["disk"] = diskData
var/list/new_buffers = list()
- for(var/datum/dna2/record/buf in src.buffers)
+ for(var/datum/dna2/record/buf in buffers)
new_buffers += list(buf.GetData())
data["buffers"]=new_buffers
@@ -477,7 +463,7 @@
data["selectedUITargetHex"] = selected_ui_target_hex
var/occupantData[0]
- if(!src.connected.occupant || !src.connected.occupant.dna)
+ if(!connected.occupant || !connected.occupant.dna)
occupantData["name"] = null
occupantData["stat"] = null
occupantData["isViableSubject"] = null
@@ -492,7 +478,7 @@
occupantData["name"] = connected.occupant.dna.real_name
occupantData["stat"] = connected.occupant.stat
occupantData["isViableSubject"] = 1
- if((NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !src.connected.occupant.dna || (NO_DNA in connected.occupant.dna.species.species_traits))
+ if((NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna || (NO_DNA in connected.occupant.dna.species.species_traits))
occupantData["isViableSubject"] = 0
occupantData["health"] = connected.occupant.health
occupantData["maxHealth"] = connected.occupant.maxHealth
@@ -501,7 +487,7 @@
occupantData["uniqueIdentity"] = connected.occupant.dna.uni_identity
occupantData["structuralEnzymes"] = connected.occupant.dna.struc_enzymes
occupantData["radiationLevel"] = connected.occupant.radiation
- data["occupant"] = occupantData;
+ data["occupant"] = occupantData
data["isBeakerLoaded"] = connected.beaker ? 1 : 0
data["beakerLabel"] = null
@@ -516,173 +502,173 @@
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
if(..())
- return 0 // don't update uis
+ return FALSE // don't update uis
if(!istype(usr.loc, /turf))
- return 0 // don't update uis
- if(!src || !src.connected)
- return 0 // don't update uis
+ return FALSE // don't update uis
+ if(!src || !connected)
+ return FALSE // don't update uis
if(irradiating) // Make sure that it isn't already irradiating someone...
- return 0 // don't update uis
+ return FALSE // don't update uis
add_fingerprint(usr)
if(href_list["selectMenuKey"])
selected_menu_key = href_list["selectMenuKey"]
- return 1 // return 1 forces an update to all Nano uis attached to src
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["toggleLock"])
- if((src.connected && src.connected.occupant))
- src.connected.locked = !( src.connected.locked )
- return 1 // return 1 forces an update to all Nano uis attached to src
+ if((connected && connected.occupant))
+ connected.locked = !(connected.locked)
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["pulseRadiation"])
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
SSnanoui.update_uis(src) // update all UIs attached to src
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
irradiating = 0
- src.connected.locked = lock_state
+ connected.locked = lock_state
- if(!src.connected.occupant)
- return 1 // return 1 forces an update to all Nano uis attached to src
+ if(!connected.occupant)
+ return TRUE // return 1 forces an update to all Nano uis attached to src
- var/radiation = (((src.radiation_intensity*3)+src.radiation_duration*3) / connected.damage_coeff)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
- if(src.connected.radiation_check())
- return 1
+ var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff)
+ connected.occupant.apply_effect(radiation, IRRADIATE, 0)
+ if(connected.radiation_check())
+ return TRUE
if(prob(95))
if(prob(75))
- randmutb(src.connected.occupant)
+ randmutb(connected.occupant)
else
- randmuti(src.connected.occupant)
+ randmuti(connected.occupant)
else
if(prob(95))
- randmutg(src.connected.occupant)
+ randmutg(connected.occupant)
else
- randmuti(src.connected.occupant)
+ randmuti(connected.occupant)
- return 1 // return 1 forces an update to all Nano uis attached to src
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["radiationDuration"])
if(text2num(href_list["radiationDuration"]) > 0)
- if(src.radiation_duration < 20)
- src.radiation_duration += 2
+ if(radiation_duration < 20)
+ radiation_duration += 2
else
- if(src.radiation_duration > 2)
- src.radiation_duration -= 2
- return 1 // return 1 forces an update to all Nano uis attached to src
+ if(radiation_duration > 2)
+ radiation_duration -= 2
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["radiationIntensity"])
if(text2num(href_list["radiationIntensity"]) > 0)
- if(src.radiation_intensity < 10)
- src.radiation_intensity++
+ if(radiation_intensity < 10)
+ radiation_intensity++
else
- if(src.radiation_intensity > 1)
- src.radiation_intensity--
- return 1 // return 1 forces an update to all Nano uis attached to src
+ if(radiation_intensity > 1)
+ radiation_intensity--
+ return TRUE // return 1 forces an update to all Nano uis attached to src
////////////////////////////////////////////////////////
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) > 0)
- if(src.selected_ui_target < 15)
- src.selected_ui_target++
- src.selected_ui_target_hex = src.selected_ui_target
+ if(selected_ui_target < 15)
+ selected_ui_target++
+ selected_ui_target_hex = selected_ui_target
switch(selected_ui_target)
if(10)
- src.selected_ui_target_hex = "A"
+ selected_ui_target_hex = "A"
if(11)
- src.selected_ui_target_hex = "B"
+ selected_ui_target_hex = "B"
if(12)
- src.selected_ui_target_hex = "C"
+ selected_ui_target_hex = "C"
if(13)
- src.selected_ui_target_hex = "D"
+ selected_ui_target_hex = "D"
if(14)
- src.selected_ui_target_hex = "E"
+ selected_ui_target_hex = "E"
if(15)
- src.selected_ui_target_hex = "F"
+ selected_ui_target_hex = "F"
else
- src.selected_ui_target = 0
- src.selected_ui_target_hex = 0
- return 1 // return 1 forces an update to all Nano uis attached to src
+ selected_ui_target = 0
+ selected_ui_target_hex = 0
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) < 1)
- if(src.selected_ui_target > 0)
- src.selected_ui_target--
- src.selected_ui_target_hex = src.selected_ui_target
+ if(selected_ui_target > 0)
+ selected_ui_target--
+ selected_ui_target_hex = selected_ui_target
switch(selected_ui_target)
if(10)
- src.selected_ui_target_hex = "A"
+ selected_ui_target_hex = "A"
if(11)
- src.selected_ui_target_hex = "B"
+ selected_ui_target_hex = "B"
if(12)
- src.selected_ui_target_hex = "C"
+ selected_ui_target_hex = "C"
if(13)
- src.selected_ui_target_hex = "D"
+ selected_ui_target_hex = "D"
if(14)
- src.selected_ui_target_hex = "E"
+ selected_ui_target_hex = "E"
else
- src.selected_ui_target = 15
- src.selected_ui_target_hex = "F"
- return 1 // return 1 forces an update to all Nano uis attached to src
+ selected_ui_target = 15
+ selected_ui_target_hex = "F"
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["selectUIBlock"] && href_list["selectUISubblock"]) // This chunk of code updates selected block / sub-block based on click
var/select_block = text2num(href_list["selectUIBlock"])
var/select_subblock = text2num(href_list["selectUISubblock"])
if((select_block <= DNA_UI_LENGTH) && (select_block >= 1))
- src.selected_ui_block = select_block
+ selected_ui_block = select_block
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
- src.selected_ui_subblock = select_subblock
- return 1 // return 1 forces an update to all Nano uis attached to src
+ selected_ui_subblock = select_subblock
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["pulseUIRadiation"])
- var/block = src.connected.occupant.dna.GetUISubBlock(src.selected_ui_block,src.selected_ui_subblock)
+ var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block, selected_ui_subblock)
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
SSnanoui.update_uis(src) // update all UIs attached to src
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
irradiating = 0
- src.connected.locked = lock_state
+ connected.locked = lock_state
- if(!src.connected.occupant)
- return 1
+ if(!connected.occupant)
+ return TRUE
- if(prob((80 + (src.radiation_duration / 2))))
- var/radiation = (src.radiation_intensity+src.radiation_duration)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
+ if(prob((80 + (radiation_duration / 2))))
+ var/radiation = (radiation_intensity + radiation_duration)
+ connected.occupant.apply_effect(radiation,IRRADIATE,0)
- if(src.connected.radiation_check())
- return 1
+ if(connected.radiation_check())
+ return TRUE
- block = miniscrambletarget(num2text(selected_ui_target), src.radiation_intensity, src.radiation_duration)
- src.connected.occupant.dna.SetUISubBlock(src.selected_ui_block,src.selected_ui_subblock,block)
- src.connected.occupant.UpdateAppearance()
+ block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
+ connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block)
+ connected.occupant.UpdateAppearance()
else
- var/radiation = ((src.radiation_intensity*2)+src.radiation_duration)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
- if(src.connected.radiation_check())
- return 1
+ var/radiation = ((radiation_intensity * 2) + radiation_duration)
+ connected.occupant.apply_effect(radiation, IRRADIATE, 0)
+ if(connected.radiation_check())
+ return TRUE
- if(prob(20+src.radiation_intensity))
- randmutb(src.connected.occupant)
- domutcheck(src.connected.occupant,src.connected)
+ if(prob(20 + radiation_intensity))
+ randmutb(connected.occupant)
+ domutcheck(connected.occupant, connected)
else
- randmuti(src.connected.occupant)
- src.connected.occupant.UpdateAppearance()
- return 1 // return 1 forces an update to all Nano uis attached to src
+ randmuti(connected.occupant)
+ connected.occupant.UpdateAppearance()
+ return TRUE // return 1 forces an update to all Nano uis attached to src
////////////////////////////////////////////////////////
if(href_list["injectRejuvenators"])
if(!connected.occupant)
- return 0
+ return FALSE
var/inject_amount = round(text2num(href_list["injectRejuvenators"]), 5) // round to nearest 5
if(inject_amount < 0) // Since the user can actually type the commands himself, some sanity checking
inject_amount = 0
@@ -690,7 +676,7 @@
inject_amount = 50
connected.beaker.reagents.trans_to(connected.occupant, inject_amount)
connected.beaker.reagents.reaction(connected.occupant)
- return 1 // return 1 forces an update to all Nano uis attached to src
+ return TRUE // return 1 forces an update to all Nano uis attached to src
////////////////////////////////////////////////////////
@@ -698,73 +684,73 @@
var/select_block = text2num(href_list["selectSEBlock"])
var/select_subblock = text2num(href_list["selectSESubblock"])
if((select_block <= DNA_SE_LENGTH) && (select_block >= 1))
- src.selected_se_block = select_block
+ selected_se_block = select_block
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
- src.selected_se_subblock = select_subblock
+ selected_se_subblock = select_subblock
//testing("User selected block [selected_se_block] (sent [select_block]), subblock [selected_se_subblock] (sent [select_block]).")
- return 1 // return 1 forces an update to all Nano uis attached to src
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["pulseSERadiation"])
- var/block = src.connected.occupant.dna.GetSESubBlock(src.selected_se_block,src.selected_se_subblock)
+ var/block = connected.occupant.dna.GetSESubBlock(selected_se_block, selected_se_subblock)
//var/original_block=block
- //testing("Irradiating SE block [src.selected_se_block]:[src.selected_se_subblock] ([block])...")
+ //testing("Irradiating SE block [selected_se_block]:[selected_se_subblock] ([block])...")
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1 //lock it
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
SSnanoui.update_uis(src) // update all UIs attached to src
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
irradiating = 0
- src.connected.locked = lock_state
+ connected.locked = lock_state
- if(src.connected.occupant)
- if(prob((80 + ((src.radiation_duration / 2) + (connected.precision_coeff ** 3)))))
- var/radiation = ((src.radiation_intensity+src.radiation_duration) / connected.damage_coeff)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
+ if(connected.occupant)
+ if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3)))))
+ var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
+ connected.occupant.apply_effect(radiation, IRRADIATE, 0)
- if(src.connected.radiation_check())
+ if(connected.radiation_check())
return 1
var/real_SE_block=selected_se_block
- block = miniscramble(block, src.radiation_intensity, src.radiation_duration)
+ block = miniscramble(block, radiation_intensity, radiation_duration)
if(prob(20))
- if(src.selected_se_block > 1 && src.selected_se_block < DNA_SE_LENGTH/2)
+ if(selected_se_block > 1 && selected_se_block < DNA_SE_LENGTH/2)
real_SE_block++
- else if(src.selected_se_block > DNA_SE_LENGTH/2 && src.selected_se_block < DNA_SE_LENGTH)
+ else if(selected_se_block > DNA_SE_LENGTH/2 && selected_se_block < DNA_SE_LENGTH)
real_SE_block--
- //testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
- connected.occupant.dna.SetSESubBlock(real_SE_block,selected_se_subblock,block)
- domutcheck(src.connected.occupant,src.connected)
+ //testing("Irradiated SE block [real_SE_block]:[selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
+ connected.occupant.dna.SetSESubBlock(real_SE_block, selected_se_subblock, block)
+ domutcheck(connected.occupant, connected)
else
- var/radiation = (((src.radiation_intensity*2)+src.radiation_duration) / connected.damage_coeff)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
+ var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff)
+ connected.occupant.apply_effect(radiation, IRRADIATE, 0)
- if(src.connected.radiation_check())
+ if(connected.radiation_check())
return 1
- if(prob(80-src.radiation_duration))
+ if(prob(80 - radiation_duration))
//testing("Random bad mut!")
- randmutb(src.connected.occupant)
- domutcheck(src.connected.occupant,src.connected)
+ randmutb(connected.occupant)
+ domutcheck(connected.occupant, connected)
else
- randmuti(src.connected.occupant)
+ randmuti(connected.occupant)
//testing("Random identity mut!")
- src.connected.occupant.UpdateAppearance()
- return 1 // return 1 forces an update to all Nano uis attached to src
+ connected.occupant.UpdateAppearance()
+ return TRUE // return 1 forces an update to all Nano uis attached to src
if(href_list["ejectBeaker"])
if(connected.beaker)
var/obj/item/reagent_containers/glass/B = connected.beaker
B.forceMove(connected.loc)
connected.beaker = null
- return 1
+ return TRUE
if(href_list["ejectOccupant"])
- connected.eject_occupant()
- return 1
+ connected.eject_occupant(usr)
+ return TRUE
// Transfer Buffer Management
if(href_list["bufferOption"])
@@ -772,113 +758,113 @@
// These bufferOptions do not require a bufferId
if(bufferOption == "wipeDisk")
- if((isnull(src.disk)) || (src.disk.read_only))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
+ if((isnull(disk)) || (disk.read_only))
+ //temphtml = "Invalid disk. Please try again."
+ return FALSE
- src.disk.buf=null
- //src.temphtml = "Data saved."
- return 1
+ disk.buf = null
+ //temphtml = "Data saved."
+ return TRUE
if(bufferOption == "ejectDisk")
- if(!src.disk)
+ if(!disk)
return
- src.disk.forceMove(get_turf(src))
- src.disk = null
- return 1
+ disk.forceMove(get_turf(src))
+ disk = null
+ return TRUE
// All bufferOptions from here on require a bufferId
if(!href_list["bufferId"])
- return 0
+ return FALSE
var/bufferId = text2num(href_list["bufferId"])
if(bufferId < 1 || bufferId > 3)
- return 0 // Not a valid buffer id
+ return FALSE // Not a valid buffer id
if(bufferOption == "saveUI")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf = new
databuf.types = DNA2_BUF_UI // DNA2_BUF_UE
- databuf.dna = src.connected.occupant.dna.Clone()
+ databuf.dna = connected.occupant.dna.Clone()
if(ishuman(connected.occupant))
databuf.dna.real_name=connected.occupant.name
databuf.name = "Unique Identifier"
- src.buffers[bufferId] = databuf
- return 1
+ buffers[bufferId] = databuf
+ return TRUE
if(bufferOption == "saveUIAndUE")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf = new
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
- databuf.dna = src.connected.occupant.dna.Clone()
+ databuf.dna = connected.occupant.dna.Clone()
if(ishuman(connected.occupant))
databuf.dna.real_name=connected.occupant.dna.real_name
databuf.name = "Unique Identifier + Unique Enzymes"
- src.buffers[bufferId] = databuf
- return 1
+ buffers[bufferId] = databuf
+ return TRUE
if(bufferOption == "saveSE")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf = new
databuf.types = DNA2_BUF_SE
- databuf.dna = src.connected.occupant.dna.Clone()
+ databuf.dna = connected.occupant.dna.Clone()
if(ishuman(connected.occupant))
- databuf.dna.real_name=connected.occupant.dna.real_name
+ databuf.dna.real_name = connected.occupant.dna.real_name
databuf.name = "Structural Enzymes"
- src.buffers[bufferId] = databuf
- return 1
+ buffers[bufferId] = databuf
+ return TRUE
if(bufferOption == "clear")
- src.buffers[bufferId]=new /datum/dna2/record()
- return 1
+ buffers[bufferId] = new /datum/dna2/record()
+ return TRUE
if(bufferOption == "changeLabel")
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ var/datum/dna2/record/buf = buffers[bufferId]
var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null)
buf.name = text
- src.buffers[bufferId] = buf
- return 1
+ buffers[bufferId] = buf
+ return TRUE
if(bufferOption == "transfer")
- if(!src.connected.occupant || (NOCLONE in src.connected.occupant.mutations && connected.scan_level < 3) || !src.connected.occupant.dna)
- return 1
+ if(!connected.occupant || (NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna)
+ return TRUE
irradiating = 2
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
SSnanoui.update_uis(src) // update all UIs attached to src
sleep(2 SECONDS)
irradiating = 0
- src.connected.locked = lock_state
+ connected.locked = lock_state
var/radiation = (rand(20,50) / connected.damage_coeff)
- src.connected.occupant.apply_effect(radiation,IRRADIATE,0)
+ connected.occupant.apply_effect(radiation, IRRADIATE, 0)
- if(src.connected.radiation_check())
- return 1
+ if(connected.radiation_check())
+ return TRUE
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ var/datum/dna2/record/buf = buffers[bufferId]
if((buf.types & DNA2_BUF_UI))
if((buf.types & DNA2_BUF_UE))
- src.connected.occupant.real_name = buf.dna.real_name
- src.connected.occupant.name = buf.dna.real_name
- src.connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
+ connected.occupant.real_name = buf.dna.real_name
+ connected.occupant.name = buf.dna.real_name
+ connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
else if(buf.types & DNA2_BUF_SE)
- src.connected.occupant.dna.SE = buf.dna.SE.Copy()
- src.connected.occupant.dna.UpdateSE()
- domutcheck(src.connected.occupant,src.connected)
- return 1
+ connected.occupant.dna.SE = buf.dna.SE.Copy()
+ connected.occupant.dna.UpdateSE()
+ domutcheck(connected.occupant, connected)
+ return TRUE
if(bufferOption == "createInjector")
if(injector_ready && !waiting_for_user_input)
var/success = 1
var/obj/item/dnainjector/I = new /obj/item/dnainjector
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ var/datum/dna2/record/buf = buffers[bufferId]
buf = buf.copy()
if(href_list["createBlockInjector"])
waiting_for_user_input=1
@@ -893,35 +879,35 @@
I.buf = buf
waiting_for_user_input = 0
if(success)
- I.forceMove(src.loc)
+ I.forceMove(loc)
I.name += " ([buf.name])"
if(connected)
I.damage_coeff = connected.damage_coeff
- src.injector_ready = 0
+ injector_ready = FALSE
spawn(300)
- src.injector_ready = 1
- return 1
+ injector_ready = TRUE
+ return TRUE
if(bufferOption == "loadDisk")
- if((isnull(src.disk)) || (!src.disk.buf))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
+ if((isnull(disk)) || (!disk.buf))
+ //temphtml = "Invalid disk. Please try again."
+ return FALSE
- src.buffers[bufferId]=src.disk.buf.copy()
- //src.temphtml = "Data loaded."
- return 1
+ buffers[bufferId] = disk.buf.copy()
+ //temphtml = "Data loaded."
+ return TRUE
if(bufferOption == "saveDisk")
- if((isnull(src.disk)) || (src.disk.read_only))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
+ if((isnull(disk)) || (disk.read_only))
+ //temphtml = "Invalid disk. Please try again."
+ return FALSE
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ var/datum/dna2/record/buf = buffers[bufferId]
- src.disk.buf = buf.copy()
- src.disk.name = "data disk - '[buf.dna.real_name]'"
- //src.temphtml = "Data saved."
- return 1
+ disk.buf = buf.copy()
+ disk.name = "data disk - '[buf.dna.real_name]'"
+ //temphtml = "Data saved."
+ return TRUE
/////////////////////////// DNA MACHINES
diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm
index e1af06f2ff4..8b8a86009b9 100644
--- a/code/game/dna/genes/disabilities.dm
+++ b/code/game/dna/genes/disabilities.dm
@@ -7,113 +7,144 @@
/////////////////////
/datum/dna/gene/disability
- name="DISABILITY"
+ name = "DISABILITY"
// Mutation to give (or 0)
- var/mutation=0
-
- // Disability to give (or 0)
- var/disability=0
+ var/mutation = 0
// Activation message
- var/activation_message=""
+ var/activation_message = ""
// Yay, you're no longer growing 3 arms
- var/deactivation_message=""
+ var/deactivation_message = ""
-/datum/dna/gene/disability/can_activate(var/mob/M,var/flags)
- return 1 // Always set!
+/datum/dna/gene/disability/can_activate(mob/M, flags)
+ return TRUE // Always set!
-/datum/dna/gene/disability/activate(var/mob/living/M, var/connected, var/flags)
+/datum/dna/gene/disability/activate(mob/living/M, connected, flags)
..()
- if(mutation && !(mutation in M.mutations))
- M.mutations.Add(mutation)
- if(disability)
- M.disabilities|=disability
+ M.mutations |= mutation
if(activation_message)
to_chat(M, "[activation_message]")
else
testing("[name] has no activation message.")
-/datum/dna/gene/disability/deactivate(var/mob/living/M, var/connected, var/flags)
+/datum/dna/gene/disability/deactivate(mob/living/M, connected, flags)
..()
- if(mutation && (mutation in M.mutations))
- M.mutations.Remove(mutation)
- if(disability)
- M.disabilities &= ~disability
+ M.mutations.Remove(mutation)
if(deactivation_message)
to_chat(M, "[deactivation_message]")
else
testing("[name] has no deactivation message.")
/datum/dna/gene/disability/hallucinate
- name="Hallucinate"
- activation_message="Your mind says 'Hello'."
- deactivation_message ="Sanity returns. Or does it?"
+ name = "Hallucinate"
+ activation_message = "Your mind says 'Hello'."
+ deactivation_message = "Sanity returns. Or does it?"
instability = -GENE_INSTABILITY_MODERATE
- mutation=HALLUCINATE
+ mutation = HALLUCINATE
/datum/dna/gene/disability/hallucinate/New()
- block=GLOB.hallucinationblock
+ ..()
+ block = GLOB.hallucinationblock
+
+/datum/dna/gene/disability/hallucinate/OnMobLife(mob/living/carbon/human/H)
+ if(prob(1))
+ H.Hallucinate(20)
/datum/dna/gene/disability/epilepsy
- name="Epilepsy"
- activation_message="You get a headache."
- deactivation_message ="Your headache is gone, at last."
+ name = "Epilepsy"
+ activation_message = "You get a headache."
+ deactivation_message = "Your headache is gone, at last."
instability = -GENE_INSTABILITY_MODERATE
- disability=EPILEPSY
+ mutation = EPILEPSY
/datum/dna/gene/disability/epilepsy/New()
- block=GLOB.epilepsyblock
+ ..()
+ block = GLOB.epilepsyblock
+
+/datum/dna/gene/disability/epilepsy/OnMobLife(mob/living/carbon/human/H)
+ if((prob(1) && H.paralysis < 1))
+ H.visible_message("[H] starts having a seizure!","You have a seizure!")
+ H.Paralyse(10)
+ H.Jitter(1000)
/datum/dna/gene/disability/cough
- name="Coughing"
- activation_message="You start coughing."
- deactivation_message ="Your throat stops aching."
+ name = "Coughing"
+ activation_message = "You start coughing."
+ deactivation_message = "Your throat stops aching."
instability = -GENE_INSTABILITY_MINOR
- disability=COUGHING
+ mutation = COUGHING
/datum/dna/gene/disability/cough/New()
- block=GLOB.coughblock
+ ..()
+ block = GLOB.coughblock
+
+/datum/dna/gene/disability/cough/OnMobLife(mob/living/carbon/human/H)
+ if((prob(5) && H.paralysis <= 1))
+ H.drop_item()
+ H.emote("cough")
/datum/dna/gene/disability/clumsy
- name="Clumsiness"
- activation_message="You feel lightheaded."
- deactivation_message ="You regain some control of your movements"
+ name = "Clumsiness"
+ activation_message = "You feel lightheaded."
+ deactivation_message = "You regain some control of your movements"
instability = -GENE_INSTABILITY_MINOR
- mutation=CLUMSY
+ mutation = CLUMSY
/datum/dna/gene/disability/clumsy/New()
- block=GLOB.clumsyblock
+ ..()
+ block = GLOB.clumsyblock
/datum/dna/gene/disability/tourettes
- name="Tourettes"
- activation_message="You twitch."
- deactivation_message ="Your mouth tastes like soap."
+ name = "Tourettes"
+ activation_message = "You twitch."
+ deactivation_message = "Your mouth tastes like soap."
instability = -GENE_INSTABILITY_MODERATE
- disability=TOURETTES
+ mutation = TOURETTES
/datum/dna/gene/disability/tourettes/New()
- block=GLOB.twitchblock
+ ..()
+ block = GLOB.twitchblock
+
+/datum/dna/gene/disability/tourettes/OnMobLife(mob/living/carbon/human/H)
+ if((prob(10) && H.paralysis <= 1))
+ H.Stun(10)
+ switch(rand(1, 3))
+ if(1)
+ H.emote("twitch")
+ if(2 to 3)
+ H.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
+ var/x_offset_old = H.pixel_x
+ var/y_offset_old = H.pixel_y
+ var/x_offset = H.pixel_x + rand(-2, 2)
+ var/y_offset = H.pixel_y + rand(-1, 1)
+ animate(H, pixel_x = x_offset, pixel_y = y_offset, time = 1)
+ animate(H, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1)
/datum/dna/gene/disability/nervousness
- name="Nervousness"
+ name = "Nervousness"
activation_message="You feel nervous."
deactivation_message ="You feel much calmer."
- disability=NERVOUS
+ mutation = NERVOUS
/datum/dna/gene/disability/nervousness/New()
- block=GLOB.nervousblock
+ ..()
+ block = GLOB.nervousblock
+/datum/dna/gene/disability/nervousness/OnMobLife(mob/living/carbon/human/H)
+ if(prob(10))
+ H.Stuttering(10)
/datum/dna/gene/disability/blindness
- name="Blindness"
+ name = "Blindness"
activation_message = "You can't seem to see anything."
deactivation_message = "You can see now, in case you didn't notice..."
instability = -GENE_INSTABILITY_MAJOR
- disability = BLIND
+ mutation = BLINDNESS
/datum/dna/gene/disability/blindness/New()
+ ..()
block = GLOB.blindblock
/datum/dna/gene/disability/blindness/activate(mob/M, connected, flags)
@@ -130,51 +161,54 @@
activation_message = "You feel a peculiar prickling in your eyes while your perception of colour changes."
deactivation_message ="Your eyes tingle unsettlingly, though everything seems to become alot more colourful."
instability = -GENE_INSTABILITY_MODERATE
- disability = COLOURBLIND
+ mutation = COLOURBLIND
/datum/dna/gene/disability/colourblindness/New()
- block=GLOB.colourblindblock
+ ..()
+ block = GLOB.colourblindblock
-/datum/dna/gene/disability/colourblindness/activate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/disability/colourblindness/activate(mob/M, connected, flags)
..()
M.update_client_colour() //Handle the activation of the colourblindness on the mob.
M.update_icons() //Apply eyeshine as needed.
-/datum/dna/gene/disability/colourblindness/deactivate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/disability/colourblindness/deactivate(mob/M, connected, flags)
..()
M.update_client_colour() //Handle the deactivation of the colourblindness on the mob.
M.update_icons() //Remove eyeshine as needed.
/datum/dna/gene/disability/deaf
- name="Deafness"
+ name = "Deafness"
activation_message="It's kinda quiet."
deactivation_message ="You can hear again!"
instability = -GENE_INSTABILITY_MAJOR
- disability=DEAF
+ mutation = DEAF
/datum/dna/gene/disability/deaf/New()
- block=GLOB.deafblock
+ ..()
+ block = GLOB.deafblock
-/datum/dna/gene/disability/deaf/activate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/disability/deaf/activate(mob/M, connected, flags)
..()
M.MinimumDeafTicks(1)
/datum/dna/gene/disability/nearsighted
- name="Nearsightedness"
+ name = "Nearsightedness"
activation_message="Your eyes feel weird..."
deactivation_message ="You can see clearly now"
instability = -GENE_INSTABILITY_MODERATE
- disability=NEARSIGHTED
+ mutation = NEARSIGHTED
/datum/dna/gene/disability/nearsighted/New()
- block=GLOB.glassesblock
+ ..()
+ block = GLOB.glassesblock
/datum/dna/gene/disability/nearsighted/activate(mob/living/M, connected, flags)
- . = ..()
+ ..()
M.update_nearsighted_effects()
/datum/dna/gene/disability/nearsighted/deactivate(mob/living/M, connected, flags)
- . = ..()
+ ..()
M.update_nearsighted_effects()
/datum/dna/gene/disability/lisp
@@ -186,9 +220,9 @@
/datum/dna/gene/disability/lisp/New()
..()
- block=GLOB.lispblock
+ block = GLOB.lispblock
-/datum/dna/gene/disability/lisp/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/lisp/OnSay(mob/M, message)
return replacetext(message,"s","th")
/datum/dna/gene/disability/comic
@@ -196,9 +230,10 @@
desc = "This will only bring death and destruction."
activation_message = "Uh oh!"
deactivation_message = "Well thank god that's over with."
- mutation=COMIC
+ mutation = COMIC
/datum/dna/gene/disability/comic/New()
+ ..()
block = GLOB.comicblock
/datum/dna/gene/disability/wingdings
@@ -210,9 +245,10 @@
mutation = WINGDINGS
/datum/dna/gene/disability/wingdings/New()
+ ..()
block = GLOB.wingdingsblock
-/datum/dna/gene/disability/wingdings/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/wingdings/OnSay(mob/M, message)
var/list/chars = string2charlist(message)
var/garbled_message = ""
for(var/C in chars)
diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm
index f74d0c7d2a0..1509cd098a4 100644
--- a/code/game/dna/genes/gene.dm
+++ b/code/game/dna/genes/gene.dm
@@ -11,63 +11,61 @@
/datum/dna/gene
// Display name
- var/name="BASE GENE"
+ var/name = "BASE GENE"
// Probably won't get used but why the fuck not
var/desc="Oh god who knows what this does."
// Set in initialize()!
// What gene activates this?
- var/block=0
+ var/block = 0
// Any of a number of GENE_ flags.
- var/flags=0
+ var/flags = 0
// Chance of the gene to cause adverse effects when active
- var/instability=0
+ var/instability = 0
/*
* Is the gene active in this mob's DNA?
*/
-/datum/dna/gene/proc/is_active(var/mob/M)
- return M.active_genes && type in M.active_genes
+/datum/dna/gene/proc/is_active(mob/M)
+ return M.active_genes && (type in M.active_genes)
// Return 1 if we can activate.
// HANDLE MUTCHK_FORCED HERE!
-/datum/dna/gene/proc/can_activate(var/mob/M, var/flags)
- return 0
+/datum/dna/gene/proc/can_activate(mob/M, flags)
+ return FALSE
// Called when the gene activates. Do your magic here.
-/datum/dna/gene/proc/activate(var/mob/living/M, var/connected, var/flags)
+/datum/dna/gene/proc/activate(mob/living/M, connected, flags)
M.gene_stability -= instability
- return
/**
* Called when the gene deactivates. Undo your magic here.
* Only called when the block is deactivated.
*/
-/datum/dna/gene/proc/deactivate(var/mob/living/M, var/connected, var/flags)
+/datum/dna/gene/proc/deactivate(mob/living/M, connected, flags)
M.gene_stability += instability
- return
// This section inspired by goone's bioEffects.
/**
* Called in each life() tick.
*/
-/datum/dna/gene/proc/OnMobLife(var/mob/M)
+/datum/dna/gene/proc/OnMobLife(mob/M)
return
/**
* Called when the mob dies
*/
-/datum/dna/gene/proc/OnMobDeath(var/mob/M)
+/datum/dna/gene/proc/OnMobDeath(mob/M)
return
/**
* Called when the mob says shit
*/
-/datum/dna/gene/proc/OnSay(var/mob/M, var/message)
+/datum/dna/gene/proc/OnSay(mob/M, message)
return message
/**
@@ -75,10 +73,9 @@
*
* @params M The subject.
* @params g Gender (m or f)
-* @params fat Fat? (0 or 1)
*/
-/datum/dna/gene/proc/OnDrawUnderlays(var/mob/M, var/g, var/fat)
- return 0
+/datum/dna/gene/proc/OnDrawUnderlays(mob/M, g)
+ return FALSE
/////////////////////
@@ -94,34 +91,34 @@
/datum/dna/gene/basic
- name="BASIC GENE"
+ name = "BASIC GENE"
// Mutation to give
- var/mutation=0
+ var/mutation = 0
// Activation probability
- var/activation_prob=100
+ var/activation_prob = 100
// Possible activation messages
- var/list/activation_messages=list()
+ var/list/activation_messages = list()
// Possible deactivation messages
- var/list/deactivation_messages=list()
+ var/list/deactivation_messages = list()
-/datum/dna/gene/basic/can_activate(var/mob/M,var/flags)
+/datum/dna/gene/basic/can_activate(mob/M, flags)
if(flags & MUTCHK_FORCED)
- return 1
+ return TRUE
// Probability check
return prob(activation_prob)
-/datum/dna/gene/basic/activate(var/mob/M)
+/datum/dna/gene/basic/activate(mob/M, connected, flags)
..()
M.mutations.Add(mutation)
if(activation_messages.len)
var/msg = pick(activation_messages)
to_chat(M, "[msg]")
-/datum/dna/gene/basic/deactivate(var/mob/M)
+/datum/dna/gene/basic/deactivate(mob/living/M, connected, flags)
..()
M.mutations.Remove(mutation)
if(deactivation_messages.len)
diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm
index 3d794f1a70d..7615f737cd0 100644
--- a/code/game/dna/genes/goon_disabilities.dm
+++ b/code/game/dna/genes/goon_disabilities.dm
@@ -13,13 +13,13 @@
activation_message = "You feel unable to express yourself at all."
deactivation_message = "You feel able to speak freely again."
instability = -GENE_INSTABILITY_MODERATE
- disability = MUTE
+ mutation = MUTE
/datum/dna/gene/disability/mute/New()
..()
- block=GLOB.muteblock
+ block = GLOB.muteblock
-/datum/dna/gene/disability/mute/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/mute/OnSay(mob/M, message)
return ""
////////////////////////////////////////
@@ -36,30 +36,29 @@
/datum/dna/gene/disability/radioactive/New()
..()
- block=GLOB.radblock
+ block = GLOB.radblock
-/datum/dna/gene/disability/radioactive/can_activate(var/mob/M,var/flags)
+/datum/dna/gene/disability/radioactive/can_activate(mob/M, flags)
if(!..())
- return 0
+ return FALSE
if(ishuman(M))
var/mob/living/carbon/human/H = M
if((RADIMMUNE in H.dna.species.species_traits) && !(flags & MUTCHK_FORCED))
- return 0
- return 1
+ return FALSE
+ return TRUE
-/datum/dna/gene/disability/radioactive/OnMobLife(var/mob/living/owner)
- var/radiation_amount = abs(min(owner.radiation - 20,0))
- owner.apply_effect(radiation_amount, IRRADIATE)
- for(var/mob/living/L in range(1, owner))
- if(L == owner)
+/datum/dna/gene/disability/radioactive/OnMobLife(mob/living/carbon/human/H)
+ var/radiation_amount = abs(min(H.radiation - 20,0))
+ H.apply_effect(radiation_amount, IRRADIATE)
+ for(var/mob/living/L in range(1, H))
+ if(L == H)
continue
- to_chat(L, "You are enveloped by a soft green glow emanating from [owner].")
+ to_chat(L, "You are enveloped by a soft green glow emanating from [H].")
L.apply_effect(5, IRRADIATE)
- return
-/datum/dna/gene/disability/radioactive/OnDrawUnderlays(var/mob/M,var/g,var/fat)
- return "rads[fat]_s"
+/datum/dna/gene/disability/radioactive/OnDrawUnderlays(mob/M, g)
+ return "rads_s"
////////////////////////////////////////
// Other disabilities
@@ -76,7 +75,7 @@
/datum/dna/gene/disability/fat/New()
..()
- block=GLOB.fatblock
+ block = GLOB.fatblock
// WAS: /datum/bioEffect/chav
/datum/dna/gene/disability/speech/chav
@@ -88,9 +87,9 @@
/datum/dna/gene/disability/speech/chav/New()
..()
- block=GLOB.chavblock
+ block = GLOB.chavblock
-/datum/dna/gene/disability/speech/chav/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/speech/chav/OnSay(mob/M, message)
// THIS ENTIRE THING BEGS FOR REGEX
message = replacetext(message,"dick","prat")
message = replacetext(message,"comdom","knob'ead")
@@ -127,9 +126,9 @@
/datum/dna/gene/disability/speech/swedish/New()
..()
- block=GLOB.swedeblock
+ block = GLOB.swedeblock
-/datum/dna/gene/disability/speech/swedish/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/speech/swedish/OnSay(mob/M, message)
// svedish
message = replacetextEx(message,"W","V")
message = replacetextEx(message,"w","v")
@@ -157,10 +156,10 @@
/datum/dna/gene/disability/unintelligable/New()
..()
- block=GLOB.scrambleblock
+ block = GLOB.scrambleblock
-/datum/dna/gene/disability/unintelligable/OnSay(var/mob/M, var/message)
- var/prefix=copytext(message,1,2)
+/datum/dna/gene/disability/unintelligable/OnSay(mob/M, message)
+ var/prefix = copytext(message,1,2)
if(prefix == ";")
message = copytext(message,2)
else if(prefix in list(":","#"))
@@ -175,7 +174,7 @@
var/cword = pick(words)
words.Remove(cword)
var/suffix = copytext(cword,length(cword)-1,length(cword))
- while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
+ while(length(cword)>0 && (suffix in list(".",",",";","!",":","?")))
cword = copytext(cword,1 ,length(cword)-1)
suffix = copytext(cword,length(cword)-1,length(cword) )
if(length(cword))
@@ -197,7 +196,7 @@
/datum/dna/gene/disability/strong/New()
..()
- block=GLOB.strongblock
+ block = GLOB.strongblock
// WAS: /datum/bioEffect/horns
/datum/dna/gene/disability/horns
@@ -209,9 +208,9 @@
/datum/dna/gene/disability/horns/New()
..()
- block=GLOB.hornsblock
+ block = GLOB.hornsblock
-/datum/dna/gene/disability/horns/OnDrawUnderlays(var/mob/M,var/g,var/fat)
+/datum/dna/gene/disability/horns/OnDrawUnderlays(mob/M, g)
return "horns_s"
////////////////////////////////////////////////////////////////////////
@@ -223,7 +222,7 @@
deactivation_messages = list("You no longer feel uncomfortably hot.")
mutation = IMMOLATE
- spelltype=/obj/effect/proc_holder/spell/targeted/immolate
+ spelltype = /obj/effect/proc_holder/spell/targeted/immolate
/datum/dna/gene/basic/grant_spell/immolate/New()
..()
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index fd2f300e8fb..87bbdf97c5c 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -2,26 +2,28 @@
// WAS: /datum/bioEffect/alcres
/datum/dna/gene/basic/sober
- name="Sober"
- activation_messages=list("You feel unusually sober.")
+ name = "Sober"
+ activation_messages = list("You feel unusually sober.")
deactivation_messages = list("You feel like you could use a stiff drink.")
- mutation=SOBER
+ mutation = SOBER
/datum/dna/gene/basic/sober/New()
- block=GLOB.soberblock
+ ..()
+ block = GLOB.soberblock
//WAS: /datum/bioEffect/psychic_resist
/datum/dna/gene/basic/psychic_resist
- name="Psy-Resist"
+ name = "Psy-Resist"
desc = "Boosts efficiency in sectors of the brain commonly associated with meta-mental energies."
activation_messages = list("Your mind feels closed.")
deactivation_messages = list("You feel oddly exposed.")
- mutation=PSY_RESIST
+ mutation = PSY_RESIST
/datum/dna/gene/basic/psychic_resist/New()
- block=GLOB.psyresistblock
+ ..()
+ block = GLOB.psyresistblock
/////////////////////////
// Stealth Enhancers
@@ -30,16 +32,16 @@
/datum/dna/gene/basic/stealth
instability = GENE_INSTABILITY_MODERATE
-/datum/dna/gene/basic/stealth/can_activate(var/mob/M, var/flags)
+/datum/dna/gene/basic/stealth/can_activate(mob/M, flags)
// Can only activate one of these at a time.
if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes))
testing("Cannot activate [type]: /datum/dna/gene/basic/stealth in M.active_genes.")
- return 0
- return ..(M,flags)
+ return FALSE
+ return ..()
-/datum/dna/gene/basic/stealth/deactivate(var/mob/M)
- ..(M)
- M.alpha=255
+/datum/dna/gene/basic/stealth/deactivate(mob/living/M, connected, flags)
+ ..()
+ M.alpha = 255
// WAS: /datum/bioEffect/darkcloak
/datum/dna/gene/basic/stealth/darkcloak
@@ -47,13 +49,14 @@
desc = "Enables the subject to bend low levels of light around themselves, creating a cloaking effect."
activation_messages = list("You begin to fade into the shadows.")
deactivation_messages = list("You become fully visible.")
- activation_prob=25
+ activation_prob = 25
mutation = CLOAK
/datum/dna/gene/basic/stealth/darkcloak/New()
- block=GLOB.shadowblock
+ ..()
+ block = GLOB.shadowblock
-/datum/dna/gene/basic/stealth/darkcloak/OnMobLife(var/mob/M)
+/datum/dna/gene/basic/stealth/darkcloak/OnMobLife(mob/M)
var/turf/simulated/T = get_turf(M)
if(!istype(T))
return
@@ -69,13 +72,14 @@
desc = "The subject becomes able to subtly alter light patterns to become invisible, as long as they remain still."
activation_messages = list("You feel one with your surroundings.")
deactivation_messages = list("You feel oddly visible.")
- activation_prob=25
+ activation_prob = 25
mutation = CHAMELEON
/datum/dna/gene/basic/stealth/chameleon/New()
- block=GLOB.chameleonblock
+ ..()
+ block = GLOB.chameleonblock
-/datum/dna/gene/basic/stealth/chameleon/OnMobLife(var/mob/M)
+/datum/dna/gene/basic/stealth/chameleon/OnMobLife(mob/M)
if((world.time - M.last_movement) >= 30 && !M.stat && M.canmove && !M.restrained())
M.alpha -= 25
else
@@ -86,27 +90,27 @@
/datum/dna/gene/basic/grant_spell
var/obj/effect/proc_holder/spell/spelltype
-/datum/dna/gene/basic/grant_spell/activate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/grant_spell/activate(mob/M, connected, flags)
M.AddSpell(new spelltype(null))
..()
- return 1
+ return TRUE
-/datum/dna/gene/basic/grant_spell/deactivate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/grant_spell/deactivate(mob/M, connected, flags)
for(var/obj/effect/proc_holder/spell/S in M.mob_spell_list)
if(istype(S, spelltype))
M.RemoveSpell(S)
..()
- return 1
+ return TRUE
/datum/dna/gene/basic/grant_verb
var/verbtype
-/datum/dna/gene/basic/grant_verb/activate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/grant_verb/activate(mob/M, connected, flags)
..()
M.verbs += verbtype
- return 1
+ return TRUE
-/datum/dna/gene/basic/grant_verb/deactivate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/grant_verb/deactivate(mob/M, connected, flags)
..()
M.verbs -= verbtype
@@ -183,8 +187,6 @@
new/obj/effect/self_deleting(C.loc, icon('icons/effects/genetics.dmi', "cryokinesis"))
- return
-
/obj/effect/self_deleting
density = 0
opacity = 0
@@ -193,12 +195,11 @@
desc = ""
//layer = 15
-/obj/effect/self_deleting/New(var/atom/location, var/icon/I, var/duration = 20, var/oname = "something")
- src.name = oname
+/obj/effect/self_deleting/New(atom/location, icon/I, duration = 20, oname = "something")
+ name = oname
loc=location
- src.icon = I
- spawn(duration)
- qdel(src)
+ icon = I
+ QDEL_IN(src, duration)
///////////////////////////////////////////////////////////////////////////////////////////
@@ -255,7 +256,7 @@
/obj/item/implant
)
-/obj/effect/proc_holder/spell/targeted/eat/proc/doHeal(var/mob/user)
+/obj/effect/proc_holder/spell/targeted/eat/proc/doHeal(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
for(var/name in H.bodyparts_by_name)
@@ -300,12 +301,12 @@
perform(targets, user = user)
/obj/effect/proc_holder/spell/targeted/eat/proc/check_mouth(mob/user = usr)
- var/can_eat = 1
+ var/can_eat = TRUE
if(iscarbon(user))
var/mob/living/carbon/C = user
if((C.head && (C.head.flags_cover & HEADCOVERSMOUTH)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSMOUTH) && !C.wear_mask.mask_adjusted))
to_chat(C, "Your mouth is covered, preventing you from eating!")
- can_eat = 0
+ can_eat = FALSE
return can_eat
/obj/effect/proc_holder/spell/targeted/eat/cast(list/targets, mob/user = usr)
@@ -320,17 +321,17 @@
if(!istype(limb))
to_chat(user, "You can't eat this part of them!")
revert_cast()
- return 0
+ return FALSE
if(istype(limb,/obj/item/organ/external/head))
// Bullshit, but prevents being unable to clone someone.
to_chat(user, "You try to put \the [limb] in your mouth, but [the_item.p_their()] ears tickle your throat!")
revert_cast()
- return 0
+ return FALSE
if(istype(limb,/obj/item/organ/external/chest))
// Bullshit, but prevents being able to instagib someone.
to_chat(user, "You try to put [the_item.p_their()] [limb] in your mouth, but it's too big to fit!")
revert_cast()
- return 0
+ return FALSE
user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!")
var/oldloc = H.loc
if(!do_mob(user,H,EAT_MOB_DELAY))
@@ -350,7 +351,6 @@
playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0)
qdel(the_item)
doHeal(user)
- return
////////////////////////////////////////////////////////////////////////
@@ -387,7 +387,7 @@
action_icon_state = "genetic_jump"
/obj/effect/proc_holder/spell/targeted/leap/cast(list/targets, mob/user = usr)
- var/failure = 0
+ var/failure = FALSE
if(istype(user.loc,/mob/) || user.lying || user.stunned || user.buckled || user.stat)
to_chat(user, "You can't jump right now!")
return
@@ -397,7 +397,7 @@
for(var/mob/M in range(user, 1))
if(M.pulling == user)
if(!M.restrained() && M.stat == 0 && M.canmove && user.Adjacent(M))
- failure = 1
+ failure = TRUE
else
M.stop_pulling()
@@ -409,12 +409,12 @@
user.visible_message("[user] attempts to leap away but is slammed back down to the ground!",
"You attempt to leap away but are suddenly slammed back down to the ground!",
"You hear the flexing of powerful muscles and suddenly a crash as a body hits the floor.")
- return 0
+ return FALSE
var/prevLayer = user.layer
var/prevFlying = user.flying
user.layer = 9
- user.flying = 1
+ user.flying = TRUE
for(var/i=0, i<10, i++)
step(user, user.dir)
if(i < 5) user.pixel_y += 8
@@ -508,7 +508,7 @@
activation_messages = list("You suddenly notice more about others than you did before.")
deactivation_messages = list("You no longer feel able to sense intentions.")
instability = GENE_INSTABILITY_MINOR
- mutation=EMPATH
+ mutation = EMPATH
/datum/dna/gene/basic/grant_spell/empath/New()
..()
@@ -614,4 +614,3 @@
to_chat(M, "You sense [user.name] reading your mind.")
else if(prob(5) || M.mind.assigned_role=="Chaplain")
to_chat(M, "You sense someone intruding upon your thoughts...")
- return
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index 3b6182ecf63..583b2c75836 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -1,10 +1,11 @@
/datum/dna/gene/monkey
- name="Monkey"
+ name = "Monkey"
/datum/dna/gene/monkey/New()
- block=GLOB.monkeyblock
+ ..()
+ block = GLOB.monkeyblock
-/datum/dna/gene/monkey/can_activate(var/mob/M,var/flags)
+/datum/dna/gene/monkey/can_activate(mob/M, flags)
return ishuman(M)
/datum/dna/gene/monkey/activate(mob/living/carbon/human/H, connected, flags)
@@ -21,7 +22,7 @@
H.regenerate_icons()
H.SetStunned(1)
- H.canmove = 0
+ H.canmove = FALSE
H.icon = null
H.invisibility = 101
var/has_primitive_form = H.dna.species.primitive_form // cache this
diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm
index b0a99e05ddd..d893c64565c 100644
--- a/code/game/dna/genes/powers.dm
+++ b/code/game/dna/genes/powers.dm
@@ -3,109 +3,121 @@
///////////////////////////////////
/datum/dna/gene/basic/nobreath
- name="No Breathing"
- activation_messages=list("You feel no need to breathe.")
- deactivation_messages=list("You feel the need to breathe, once more.")
+ name = "No Breathing"
+ activation_messages = list("You feel no need to breathe.")
+ deactivation_messages = list("You feel the need to breathe, once more.")
instability = GENE_INSTABILITY_MODERATE
mutation = BREATHLESS
- activation_prob=25
+ activation_prob = 25
/datum/dna/gene/basic/nobreath/New()
+ ..()
block = GLOB.breathlessblock
/datum/dna/gene/basic/regenerate
- name="Regenerate"
- activation_messages=list("Your wounds start healing.")
- deactivation_messages=list("Your regenerative powers feel like they've vanished.")
+ name = "Regenerate"
+ activation_messages = list("Your wounds start healing.")
+ deactivation_messages = list("Your regenerative powers feel like they've vanished.")
instability = GENE_INSTABILITY_MINOR
- mutation=REGEN
+ mutation = REGEN
/datum/dna/gene/basic/regenerate/New()
- block=GLOB.regenerateblock
+ ..()
+ block = GLOB.regenerateblock
+
+/datum/dna/gene/basic/regenerate/OnMobLife(mob/living/carbon/human/H)
+ H.adjustBruteLoss(-0.1, FALSE)
+ H.adjustFireLoss(-0.1)
/datum/dna/gene/basic/increaserun
- name="Super Speed"
- activation_messages=list("You feel swift and unencumbered.")
- deactivation_messages=list("You feel slow.")
+ name = "Super Speed"
+ activation_messages = list("You feel swift and unencumbered.")
+ deactivation_messages = list("You feel slow.")
instability = GENE_INSTABILITY_MINOR
- mutation=RUN
+ mutation = RUN
/datum/dna/gene/basic/increaserun/New()
- block=GLOB.increaserunblock
+ ..()
+ block = GLOB.increaserunblock
-/datum/dna/gene/basic/increaserun/can_activate(var/mob/M,var/flags)
+/datum/dna/gene/basic/increaserun/can_activate(mob/M, flags)
if(!..())
- return 0
+ return FALSE
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.dna.species && H.dna.species.speed_mod && !(flags & MUTCHK_FORCED))
- return 0
- return 1
+ return FALSE
+ return TRUE
/datum/dna/gene/basic/heat_resist
- name="Heat Resistance"
- activation_messages=list("Your skin is icy to the touch.")
- deactivation_messages=list("Your skin no longer feels icy to the touch.")
+ name = "Heat Resistance"
+ activation_messages = list("Your skin is icy to the touch.")
+ deactivation_messages = list("Your skin no longer feels icy to the touch.")
instability = GENE_INSTABILITY_MODERATE
mutation = HEATRES
/datum/dna/gene/basic/heat_resist/New()
- block=GLOB.coldblock
+ ..()
+ block = GLOB.coldblock
-/datum/dna/gene/basic/heat_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat)
- return "cold[fat]_s"
+/datum/dna/gene/basic/heat_resist/OnDrawUnderlays(mob/M, g)
+ return "cold_s"
/datum/dna/gene/basic/cold_resist
- name="Cold Resistance"
- activation_messages=list("Your body is filled with warmth.")
- deactivation_messages=list("Your body is no longer filled with warmth.")
+ name = "Cold Resistance"
+ activation_messages = list("Your body is filled with warmth.")
+ deactivation_messages = list("Your body is no longer filled with warmth.")
instability = GENE_INSTABILITY_MODERATE
mutation = COLDRES
/datum/dna/gene/basic/cold_resist/New()
- block=GLOB.fireblock
+ ..()
+ block = GLOB.fireblock
-/datum/dna/gene/basic/cold_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat)
- return "fire[fat]_s"
+/datum/dna/gene/basic/cold_resist/OnDrawUnderlays(mob/M, g)
+ return "fire_s"
/datum/dna/gene/basic/noprints
- name="No Prints"
- activation_messages=list("Your fingers feel numb.")
- deactivation_messages=list("your fingers no longer feel numb.")
+ name = "No Prints"
+ activation_messages = list("Your fingers feel numb.")
+ deactivation_messages = list("your fingers no longer feel numb.")
instability = GENE_INSTABILITY_MINOR
- mutation=FINGERPRINTS
+ mutation = FINGERPRINTS
/datum/dna/gene/basic/noprints/New()
- block=GLOB.noprintsblock
+ ..()
+ block = GLOB.noprintsblock
/datum/dna/gene/basic/noshock
- name="Shock Immunity"
- activation_messages=list("Your skin feels dry and unreactive.")
- deactivation_messages=list("Your skin no longer feels dry and unreactive.")
+ name = "Shock Immunity"
+ activation_messages = list("Your skin feels dry and unreactive.")
+ deactivation_messages = list("Your skin no longer feels dry and unreactive.")
instability = GENE_INSTABILITY_MODERATE
- mutation=NO_SHOCK
+ mutation = NO_SHOCK
/datum/dna/gene/basic/noshock/New()
- block=GLOB.shockimmunityblock
+ ..()
+ block = GLOB.shockimmunityblock
/datum/dna/gene/basic/midget
- name="Midget"
- activation_messages=list("Everything around you seems bigger now...")
+ name = "Midget"
+ activation_messages = list("Everything around you seems bigger now...")
deactivation_messages = list("Everything around you seems to shrink...")
instability = GENE_INSTABILITY_MINOR
- mutation=DWARF
+ mutation = DWARF
/datum/dna/gene/basic/midget/New()
- block=GLOB.smallsizeblock
+ ..()
+ block = GLOB.smallsizeblock
-/datum/dna/gene/basic/midget/activate(var/mob/M, var/connected, var/flags)
- ..(M,connected,flags)
+/datum/dna/gene/basic/midget/activate(mob/M, connected, flags)
+ ..()
M.pass_flags |= PASSTABLE
M.resize = 0.8
M.update_transform()
-/datum/dna/gene/basic/midget/deactivate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/midget/deactivate(mob/M, connected, flags)
..()
M.pass_flags &= ~PASSTABLE
M.resize = 1.25
@@ -113,34 +125,32 @@
// OLD HULK BEHAVIOR
/datum/dna/gene/basic/hulk
- name="Hulk"
- activation_messages=list("Your muscles hurt.")
- deactivation_messages=list("Your muscles shrink.")
+ name = "Hulk"
+ activation_messages = list("Your muscles hurt.")
+ deactivation_messages = list("Your muscles shrink.")
instability = GENE_INSTABILITY_MAJOR
- mutation=HULK
- activation_prob=15
+ mutation = HULK
+ activation_prob = 15
/datum/dna/gene/basic/hulk/New()
- block=GLOB.hulkblock
+ ..()
+ block = GLOB.hulkblock
-/datum/dna/gene/basic/hulk/activate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/hulk/activate(mob/M, connected, flags)
..()
var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH
M.status_flags &= ~status
-/datum/dna/gene/basic/hulk/deactivate(var/mob/M, var/connected, var/flags)
+/datum/dna/gene/basic/hulk/deactivate(mob/M, connected, flags)
..()
M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH
-/datum/dna/gene/basic/hulk/OnDrawUnderlays(var/mob/M,var/g,var/fat)
+/datum/dna/gene/basic/hulk/OnDrawUnderlays(mob/M, g)
if(HULK in M.mutations)
- if(fat)
- return "hulk_[fat]_s"
- else
- return "hulk_[g]_s"
- return 0
+ return "hulk_[g]_s"
+ return FALSE
-/datum/dna/gene/basic/hulk/OnMobLife(var/mob/living/carbon/human/M)
+/datum/dna/gene/basic/hulk/OnMobLife(mob/living/carbon/human/M)
if(!istype(M))
return
if((HULK in M.mutations) && M.health <= 0)
@@ -153,15 +163,16 @@
to_chat(M, "You suddenly feel very weak.")
/datum/dna/gene/basic/xray
- name="X-Ray Vision"
- activation_messages=list("The walls suddenly disappear.")
- deactivation_messages=list("the walls around you re-appear.")
+ name = "X-Ray Vision"
+ activation_messages = list("The walls suddenly disappear.")
+ deactivation_messages = list("the walls around you re-appear.")
instability = GENE_INSTABILITY_MAJOR
- mutation=XRAY
- activation_prob=15
+ mutation = XRAY
+ activation_prob = 15
/datum/dna/gene/basic/xray/New()
- block=GLOB.xrayblock
+ ..()
+ block = GLOB.xrayblock
/datum/dna/gene/basic/xray/activate(mob/living/M, connected, flags)
..()
@@ -174,15 +185,16 @@
M.update_icons() //Remove eyeshine as needed.
/datum/dna/gene/basic/tk
- name="Telekenesis"
+ name = "Telekenesis"
activation_messages = list("You feel smarter.")
deactivation_messages = list("You feel dumber.")
instability = GENE_INSTABILITY_MAJOR
- mutation=TK
- activation_prob=15
+ mutation = TK
+ activation_prob = 15
/datum/dna/gene/basic/tk/New()
- block=GLOB.teleblock
+ ..()
+ block = GLOB.teleblock
-/datum/dna/gene/basic/tk/OnDrawUnderlays(var/mob/M,var/g,var/fat)
- return "telekinesishead[fat]_s"
+/datum/dna/gene/basic/tk/OnDrawUnderlays(mob/M, g)
+ return "telekinesishead_s"
diff --git a/code/game/dna/genes/vg_disabilities.dm b/code/game/dna/genes/vg_disabilities.dm
index d423f0bf89b..c2ad1559b6a 100644
--- a/code/game/dna/genes/vg_disabilities.dm
+++ b/code/game/dna/genes/vg_disabilities.dm
@@ -8,11 +8,11 @@
/datum/dna/gene/disability/speech/loud/New()
..()
- block=GLOB.loudblock
+ block = GLOB.loudblock
-/datum/dna/gene/disability/speech/loud/OnSay(var/mob/M, var/message)
+/datum/dna/gene/disability/speech/loud/OnSay(mob/M, message)
message = replacetext(message,".","!")
message = replacetext(message,"?","?!")
message = replacetext(message,"!","!!")
@@ -28,15 +28,15 @@
/datum/dna/gene/disability/dizzy/New()
..()
- block=GLOB.dizzyblock
+ block = GLOB.dizzyblock
-/datum/dna/gene/disability/dizzy/OnMobLife(var/mob/living/carbon/human/M)
+/datum/dna/gene/disability/dizzy/OnMobLife(mob/living/carbon/human/M)
if(!istype(M))
return
if(DIZZY in M.mutations)
M.Dizzy(300)
/datum/dna/gene/disability/dizzy/deactivate(mob/living/M, connected, flags)
- . = ..()
+ ..()
M.SetDizzy(0)
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index 5ed6c705a17..9092448e398 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -4,10 +4,10 @@
name = "Morphism"
desc = "Enables the subject to reconfigure their appearance to that of any human."
spelltype =/obj/effect/proc_holder/spell/targeted/morph
- activation_messages=list("Your body feels if can alter its appearance.")
+ activation_messages = list("Your body feels if can alter its appearance.")
deactivation_messages = list("Your body doesn't feel capable of altering its appearance.")
instability = GENE_INSTABILITY_MINOR
- mutation=MORPH
+ mutation = MORPH
/datum/dna/gene/basic/grant_spell/morph/New()
..()
@@ -29,7 +29,8 @@
action_icon_state = "genetic_morph"
/obj/effect/proc_holder/spell/targeted/morph/cast(list/targets, mob/user = usr)
- if(!ishuman(user)) return
+ if(!ishuman(user))
+ return
if(istype(user.loc,/mob/))
to_chat(user, "You can't change your appearance right now!")
@@ -173,24 +174,24 @@
M.update_dna()
- M.visible_message("[src] morphs and changes [p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!")
+ M.visible_message("[M] morphs and changes [M.p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!")
/datum/dna/gene/basic/grant_spell/remotetalk
- name="Telepathy"
- activation_messages=list("You feel you can project your thoughts.")
- deactivation_messages=list("You no longer feel you can project your thoughts.")
+ name = "Telepathy"
+ activation_messages = list("You feel you can project your thoughts.")
+ deactivation_messages = list("You no longer feel you can project your thoughts.")
instability = GENE_INSTABILITY_MINOR
- mutation=REMOTE_TALK
+ mutation = REMOTE_TALK
spelltype =/obj/effect/proc_holder/spell/targeted/remotetalk
/datum/dna/gene/basic/grant_spell/remotetalk/New()
..()
- block=GLOB.remotetalkblock
+ block = GLOB.remotetalkblock
-/datum/dna/gene/basic/grant_spell/remotetalk/activate(mob/user)
+/datum/dna/gene/basic/grant_spell/remotetalk/activate(mob/living/M, connected, flags)
..()
- user.AddSpell(new /obj/effect/proc_holder/spell/targeted/mindscan(null))
+ M.AddSpell(new /obj/effect/proc_holder/spell/targeted/mindscan(null))
/datum/dna/gene/basic/grant_spell/remotetalk/deactivate(mob/user)
..()
@@ -336,22 +337,23 @@
return ..()
/datum/dna/gene/basic/grant_spell/remoteview
- name="Remote Viewing"
- activation_messages=list("Your mind can see things from afar.")
- deactivation_messages=list("Your mind can no longer can see things from afar.")
+ name = "Remote Viewing"
+ activation_messages = list("Your mind can see things from afar.")
+ deactivation_messages = list("Your mind can no longer can see things from afar.")
instability = GENE_INSTABILITY_MINOR
- mutation=REMOTE_VIEW
+ mutation = REMOTE_VIEW
spelltype =/obj/effect/proc_holder/spell/targeted/remoteview
/datum/dna/gene/basic/grant_spell/remoteview/New()
- block=GLOB.remoteviewblock
+ ..()
+ block = GLOB.remoteviewblock
/obj/effect/proc_holder/spell/targeted/remoteview
name = "Remote View"
desc = "Spy on people from any range!"
- charge_max = 600
+ charge_max = 100
clothes_req = 0
stat_allowed = 0
@@ -363,18 +365,23 @@
/obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr)
var/list/targets = list()
- var/list/remoteviewers = new /list()
- for(var/mob/M in GLOB.living_mob_list)
+ var/list/remoteviewers = list()
+ for(var/mob/M in GLOB.alive_mob_list)
+ if(M == user)
+ continue
if(PSY_RESIST in M.mutations)
continue
if(REMOTE_VIEW in M.mutations)
remoteviewers += M
- if(!remoteviewers.len || remoteviewers.len == 1)
+ if(!LAZYLEN(remoteviewers))
to_chat(user, "No valid targets with remote view were found!")
start_recharge()
return
- targets += input("Choose the target to spy on.", "Targeting") as mob in remoteviewers
-
+ targets += input("Choose the target to spy on.", "Targeting") as null|anything in remoteviewers
+ if(!targets)
+ to_chat(user, "You decide against remote viewing.")
+ start_recharge()
+ return
perform(targets, user = user)
/obj/effect/proc_holder/spell/targeted/remoteview/cast(list/targets, mob/user = usr)
@@ -386,15 +393,15 @@
var/mob/target
- if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab/))
+ if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab))
to_chat(H, "Your mind is too busy with that telekinetic grab.")
H.remoteview_target = null
- H.reset_perspective(0)
+ H.reset_perspective()
return
if(H.client.eye != user.client.mob)
H.remoteview_target = null
- H.reset_perspective(0)
+ H.reset_perspective()
return
for(var/mob/living/L in targets)
@@ -405,4 +412,4 @@
H.reset_perspective(target)
else
H.remoteview_target = null
- H.reset_perspective(0)
+ H.reset_perspective()
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index a11e5d922ba..641167c768c 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -46,7 +46,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/datum/mind/blob = pick(possible_blobs)
infected_crew += blob
blob.special_role = SPECIAL_ROLE_BLOB
- update_blob_icons_added(blob)
blob.restricted_roles = restricted_jobs
log_game("[key_name(blob)] has been selected as a Blob")
possible_blobs -= blob
@@ -152,6 +151,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
for(var/datum/mind/blob in infected_crew)
greet_blob(blob)
+ update_blob_icons_added(blob)
if(SSshuttle)
SSshuttle.emergencyNoEscape = 1
diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm
index 893c2e0e8ac..8f6ba965222 100644
--- a/code/game/gamemodes/blob/blob_report.dm
+++ b/code/game/gamemodes/blob/blob_report.dm
@@ -3,7 +3,6 @@
var/interceptname = ""
switch(report)
if(0)
- ..()
return
if(1)
interceptname = "Level 5-6 Biohazard Response Procedures"
@@ -19,8 +18,8 @@
intercepttext += " Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12. "
intercepttext += "Message ends."
if(2)
- var/nukecode = rand(10000, 99999)
- for(var/obj/machinery/nuclearbomb/bomb in world)
+ var/nukecode = "[rand(10000, 99999)]"
+ for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
if(bomb && bomb.r_code)
if(is_station_level(bomb.z))
bomb.r_code = nukecode
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index fb26ce91698..46b1972e565 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -8,6 +8,7 @@
icon = 'icons/mob/blob.dmi'
pass_flags = PASSBLOB
faction = list(ROLE_BLOB)
+ bubble_icon = "blob"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 360
@@ -51,11 +52,12 @@
speak_emote = list("pulses")
var/obj/structure/blob/factory/factory = null
var/list/human_overlays = list()
- var/is_zombie = 0
+ var/mob/living/carbon/human/oldguy
+ var/is_zombie = FALSE
/mob/living/simple_animal/hostile/blob/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
- adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5))
+ adjustBruteLoss(clamp(0.01 * exposed_temperature, 1, 5))
/mob/living/simple_animal/hostile/blob/blobspore/CanPass(atom/movable/mover, turf/target, height=0)
@@ -85,8 +87,8 @@
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
- if(A.armor && A.armor["melee"])
- maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
+ if(A.armor && A.armor.getRating("melee"))
+ maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
maxHealth += 40
health = maxHealth
name = "blob zombie"
@@ -102,6 +104,7 @@
human_overlays = H.overlays
update_icons()
H.forceMove(src)
+ oldguy = H
visible_message("The corpse of [H.name] suddenly rises!")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
@@ -130,9 +133,9 @@
if(factory)
factory.spores -= src
factory = null
- if(contents)
- for(var/mob/M in contents)
- M.loc = get_turf(src)
+ if(oldguy)
+ oldguy.forceMove(get_turf(src))
+ oldguy = null
return ..()
diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm
index 672ab037cc5..be794b9092b 100644
--- a/code/game/gamemodes/blob/blobs/core.dm
+++ b/code/game/gamemodes/blob/blobs/core.dm
@@ -89,41 +89,40 @@
..()
-/obj/structure/blob/core/proc/create_overmind(var/client/new_overmind, var/override_delay)
+/obj/structure/blob/core/proc/create_overmind(client/new_overmind, override_delay)
if(overmind_get_delay > world.time && !override_delay)
return
- overmind_get_delay = world.time + 3000 // 5 minutes
+ overmind_get_delay = world.time + 5 MINUTES
if(overmind)
qdel(overmind)
+ INVOKE_ASYNC(src, .proc/get_new_overmind, new_overmind)
+
+/obj/structure/blob/core/proc/get_new_overmind(client/new_overmind)
var/mob/C = null
var/list/candidates = list()
-
- spawn()
- if(!new_overmind)
- if(is_offspring)
- candidates = pollCandidates("Do you want to play as a blob offspring?", ROLE_BLOB, 1)
- else
- candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
-
- if(candidates.len)
- C = pick(candidates)
+ if(!new_overmind)
+ if(is_offspring)
+ candidates = pollCandidates("Do you want to play as a blob offspring?", ROLE_BLOB, 1)
else
- C = new_overmind
+ candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
- if(C)
- var/mob/camera/blob/B = new(src.loc)
- B.key = C.key
- B.blob_core = src
- src.overmind = B
- color = overmind.blob_reagent_datum.color
- if(B.mind && !B.mind.special_role)
- B.mind.make_Overmind()
- spawn(0)
- if(is_offspring)
- B.is_offspring = TRUE
+ if(length(candidates))
+ C = pick(candidates)
+ else
+ C = new_overmind
+
+ if(C && !QDELETED(src))
+ var/mob/camera/blob/B = new(loc)
+ B.key = C.key
+ B.blob_core = src
+ overmind = B
+ color = overmind.blob_reagent_datum.color
+ if(B.mind && !B.mind.special_role)
+ B.mind.make_Overmind()
+ B.is_offspring = is_offspring
/obj/structure/blob/core/proc/lateblobtimer()
addtimer(CALLBACK(src, .proc/lateblobcheck), 50)
diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm
index 74ed59d2469..316a136afc6 100644
--- a/code/game/gamemodes/blob/overmind.dm
+++ b/code/game/gamemodes/blob/overmind.dm
@@ -35,11 +35,15 @@
color = blob_reagent_datum.complementary_color
..()
+ START_PROCESSING(SSobj, src)
-/mob/camera/blob/Life(seconds, times_fired)
+/mob/camera/blob/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/mob/camera/blob/process()
if(!blob_core)
qdel(src)
- ..()
/mob/camera/blob/Login()
..()
@@ -53,7 +57,7 @@
/mob/camera/blob/proc/add_points(var/points)
if(points != 0)
- blob_points = Clamp(blob_points + points, 0, max_blob_points)
+ blob_points = clamp(blob_points + points, 0, max_blob_points)
if(hud_used)
hud_used.blobpwrdisplay.maptext = "
[round(src.blob_points)]
"
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index bdbd875a3dc..6f2eed39499 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -357,7 +357,7 @@
if(!surrounding_turfs.len)
return
- for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in GLOB.alive_mob_list)
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
BS.LoseTarget()
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm
index 6293fd919c5..5e2c3befc9a 100644
--- a/code/game/gamemodes/blob/theblob.dm
+++ b/code/game/gamemodes/blob/theblob.dm
@@ -30,7 +30,7 @@
atmosblock = FALSE
air_update_turf(1)
GLOB.blobs -= src
- if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it
+ if(isturf(loc)) //Necessary because Expand() is screwed up and spawns a blob and then deletes it
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
return ..()
@@ -49,7 +49,7 @@
/obj/structure/blob/CanAStarPass(ID, dir, caller)
. = 0
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSBLOB)
@@ -74,9 +74,6 @@
/obj/structure/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0, var/a_color)//Todo: Fix spaceblob expand
-
- set background = BACKGROUND_ENABLED
-
RegenHealth()
if(run_action())//If we can do something here then we dont need to pulse more
@@ -179,7 +176,7 @@
return 0
var/armor_protection = 0
if(damage_flag)
- armor_protection = armor[damage_flag]
+ armor_protection = armor.getRating(damage_flag)
damage_amount = round(damage_amount * (100 - armor_protection)*0.01, 0.1)
if(overmind && damage_flag)
damage_amount = overmind.blob_reagent_datum.damage_reaction(src, damage_amount, damage_type, damage_flag)
diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
index 4663fef8b97..28afcaa9c36 100644
--- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
+++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
@@ -49,7 +49,7 @@
/obj/item/organ/internal/cyberimp/eyes/shield/ling/on_life()
..()
var/obj/item/organ/internal/eyes/E = owner.get_int_organ(/obj/item/organ/internal/eyes)
- if(owner.eye_blind || owner.eye_blurry || (owner.disabilities & BLIND) || (owner.disabilities & NEARSIGHTED) || (E.damage > 0))
+ if(owner.eye_blind || owner.eye_blurry || (BLINDNESS in owner.mutations) || (NEARSIGHTED in owner.mutations) || (E && E.damage > 0))
owner.reagents.add_reagent("oculine", 1)
/obj/item/organ/internal/cyberimp/eyes/shield/ling/prepare_eat()
@@ -76,11 +76,11 @@
var/mob/living/carbon/human/H = owner
H.weakeyes = 1
if(!H.vision_type)
- H.vision_type = new /datum/vision_override/nightvision
+ H.set_sight(/datum/vision_override/nightvision)
/obj/item/organ/internal/cyberimp/eyes/thermals/ling/remove(mob/living/carbon/M, special = 0)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.weakeyes = 0
- H.vision_type = null
+ H.set_sight(null)
..()
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index d403059b0c7..61882b85287 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -16,11 +16,8 @@
user.emote("deathgasp")
user.timeofdeath = world.time
user.status_flags |= FAKEDEATH //play dead
- user.update_stat("fakedeath sting")
+ user.updatehealth("fakedeath sting")
user.update_canmove()
- user.med_hud_set_health()
- user.handle_hud_icons_health()
- user.med_hud_set_status()
user.mind.changeling.regenerating = TRUE
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME)
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index af375cad368..98336608da4 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -23,7 +23,7 @@
return
// HIVE MIND UPLOAD/DOWNLOAD DNA
-var/list/datum/dna/hivemind_bank = list()
+GLOBAL_LIST_EMPTY(hivemind_bank)
/datum/action/changeling/hivemind_upload
name = "Hive Channel DNA"
@@ -36,7 +36,7 @@ var/list/datum/dna/hivemind_bank = list()
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
- if(!(DNA in hivemind_bank))
+ if(!(DNA in GLOB.hivemind_bank))
names += DNA.real_name
if(names.len <= 0)
@@ -51,7 +51,7 @@ var/list/datum/dna/hivemind_bank = list()
if(!chosen_dna)
return
- hivemind_bank += chosen_dna
+ GLOB.hivemind_bank += chosen_dna
to_chat(user, "We channel the DNA of [chosen_name] to the air.")
feedback_add_details("changeling_powers","HU")
return 1
@@ -75,7 +75,7 @@ var/list/datum/dna/hivemind_bank = list()
/datum/action/changeling/hivemind_download/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
- for(var/datum/dna/DNA in hivemind_bank)
+ for(var/datum/dna/DNA in GLOB.hivemind_bank)
if(!(DNA in changeling.absorbed_dna))
names[DNA.real_name] = DNA
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index d225ac6886a..d12b970d884 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -95,8 +95,8 @@
user.unEquip(user.head)
user.unEquip(user.wear_suit)
- user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, 1, 1, 1)
- user.equip_to_slot_if_possible(new helmet_type(user), slot_head, 1, 1, 1)
+ user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, TRUE, TRUE)
+ user.equip_to_slot_if_possible(new helmet_type(user), slot_head, TRUE, TRUE)
var/datum/changeling/changeling = user.mind.changeling
changeling.chem_recharge_slowdown += recharge_slowdown
@@ -321,7 +321,7 @@
if(INTENT_GRAB)
C.visible_message("[L] is grabbed by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!")
- add_attack_logs(src, C, "[src] has grabbed [C] and pulled them towards [H] with a tentacle")
+ add_attack_logs(H, C, "[H] grabbed [C] with a changeling tentacle")
C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_grab, C))
return 1
diff --git a/code/game/gamemodes/changeling/powers/spiders.dm b/code/game/gamemodes/changeling/powers/spiders.dm
index 82b2db6ac7b..778ec768e55 100644
--- a/code/game/gamemodes/changeling/powers/spiders.dm
+++ b/code/game/gamemodes/changeling/powers/spiders.dm
@@ -1,7 +1,7 @@
/datum/action/changeling/spiders
name = "Spread Infestation"
desc = "Our form divides, creating arachnids which will grow into deadly beasts."
- helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions."
+ helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 stored DNA."
button_icon_state = "spread_infestation"
chemical_cost = 45
dna_cost = 1
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index e0fc1107729..0e02df12d88 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -18,7 +18,7 @@
if((NOCLONE || SKELETON || HUSK) in target.mutations)
to_chat(user, "DNA of [target] is ruined beyond usability!")
return
- if(!istype(target) || issmall(target) || NO_DNA in target.dna.species.species_traits)
+ if(!istype(target) || issmall(target) || (NO_DNA in target.dna.species.species_traits))
to_chat(user, "[target] is not compatible with this ability.")
return
if(target.mind.changeling)
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index 94bde26674b..fbfb75b8b6a 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -36,11 +36,9 @@
to_chat(user, "We haven't prepared our sting yet!")
if(!iscarbon(target))
return
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- if(H.isSynthetic())
- to_chat(user, "This won't work on synthetics.")
- return
+ if(ismachineperson(target))
+ to_chat(user, "This won't work on synthetics.")
+ return
if(!isturf(user.loc))
return
if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0))
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 1a9dd15c65e..bf5fbb70731 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -84,8 +84,8 @@ GLOBAL_LIST_EMPTY(all_cults)
var/survivors = 0
/datum/game_mode/cult/announce()
- to_chat(world, "The current game mode is - Cult!")
- to_chat(world, "Some crewmembers are attempting to start a cult! \nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult. \nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever CentComm-allowed faith they had.")
+ to_chat(world, "The current game mode is - Cult!")
+ to_chat(world, "Some crew members are attempting to start a cult! \nCultists - complete your objectives. Convert crew members to your cause by using the convert rune. Remember - there is no you, there is only the cult. \nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever CentComm-allowed faith they had.")
/datum/game_mode/cult/pre_setup()
@@ -147,8 +147,8 @@ GLOBAL_LIST_EMPTY(all_cults)
explanation = "Free objective."
if("eldergod")
explanation = "Summon [SSticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin."
- to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]")
- cult_mind.memory += "Objective #[obj_count]: [explanation] "
+ to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]")
+ cult_mind.memory += "Objective #[obj_count]: [explanation] "
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob)
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(all_cults)
update_cult_icons_removed(cult_mind)
if(show_message)
for(var/mob/M in viewers(cult_mind.current))
- to_chat(M, "[cult_mind.current] looks like [cult_mind.current.p_they()] just reverted to [cult_mind.current.p_their()] old faith!")
+ to_chat(M, "[cult_mind.current] looks like [cult_mind.current.p_they()] just reverted to [cult_mind.current.p_their()] old faith!")
/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind)
@@ -284,11 +284,11 @@ GLOBAL_LIST_EMPTY(all_cults)
if(!check_cult_victory())
feedback_set_details("round_end_result","cult win - cult win")
feedback_set("round_end_result",acolytes_survived)
- to_chat(world, " The cult wins! It has succeeded in serving its dark masters!")
+ to_chat(world, " The cult wins! It has succeeded in serving its dark masters!")
else
feedback_set_details("round_end_result","cult loss - staff stopped the cult")
feedback_set("round_end_result",acolytes_survived)
- to_chat(world, " The staff managed to stop the cult!")
+ to_chat(world, " The staff managed to stop the cult!")
var/text = "Cultists escaped: [acolytes_survived]"
@@ -299,7 +299,7 @@ GLOBAL_LIST_EMPTY(all_cults)
switch(objectives[obj_count])
if("survive")
if(!check_survive())
- explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!"
+ explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!"
feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
else
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Fail."
@@ -307,7 +307,7 @@ GLOBAL_LIST_EMPTY(all_cults)
if("sacrifice")
if(sacrifice_target)
if(sacrifice_target in sacrificed)
- explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!"
+ explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!"
feedback_add_details("cult_objective","cult_sacrifice|SUCCESS")
else if(sacrifice_target && sacrifice_target.current)
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail."
@@ -317,7 +317,7 @@ GLOBAL_LIST_EMPTY(all_cults)
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
- explanation = "Summon [SSticker.cultdat.entity_name]. Success!"
+ explanation = "Summon [SSticker.cultdat.entity_name]. Success!"
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
else
explanation = "Summon [SSticker.cultdat.entity_name]. Fail."
@@ -332,45 +332,45 @@ GLOBAL_LIST_EMPTY(all_cults)
if("convert")//convert half the crew
if(cult.len >= convert_target)
- explanation = "Convert [convert_target] crewmembers ([cult.len] cultists at round end). Success!"
+ explanation = "Convert [convert_target] crew members ([cult.len] cultists at round end). Success!"
feedback_add_details("cult_objective","cult_convertion|SUCCESS")
else
- explanation = "Convert [convert_target] crewmembers ([cult.len] total cultists). Fail!"
+ explanation = "Convert [convert_target] crew members ([cult.len] total cultists). Fail."
feedback_add_details("cult_objective","cult_convertion|FAIL")
if("bloodspill")//cover a large portion of the station in blood
if(max_spilled_blood >= spilltarget)
- explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Success!"
+ explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Success!"
feedback_add_details("cult_objective","cult_bloodspill|SUCCESS")
else
- explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Fail!"
+ explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Fail."
feedback_add_details("cult_objective","cult_bloodspill|FAIL")
if("harvest")
if(harvested > harvest_target)
- explanation = "Offer [harvest_target] humans for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
+ explanation = "Offer [harvest_target] humanoids for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
feedback_add_details("cult_objective","cult_harvest|SUCCESS")
else
- explanation = "Offer [harvest_target] humans for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail!"
+ explanation = "Offer [harvest_target] humanoids for [SSticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail."
feedback_add_details("cult_objective","cult_harvest|FAIL")
if("hijack")
if(!escaped_shuttle)
- explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Success!"
+ explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Success!"
feedback_add_details("cult_objective","cult_hijack|SUCCESS")
else
- explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Fail!"
+ explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Fail."
feedback_add_details("cult_objective","cult_hijack|FAIL")
if("massacre")
if(survivors < massacre_target)
- explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humans left alive) Success!"
+ explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humanoids left alive) Success!"
feedback_add_details("cult_objective","cult_massacre|SUCCESS")
else
- explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humans left alive) Fail!"
+ explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humanoids left alive) Fail."
feedback_add_details("cult_objective","cult_massacre|FAIL")
- text += " Objective #[obj_count]: [explanation]"
+ text += " Objective #[obj_count]: [explanation]"
to_chat(world, text)
..()
@@ -379,7 +379,7 @@ GLOBAL_LIST_EMPTY(all_cults)
/datum/game_mode/proc/auto_declare_completion_cult()
if(cult.len || (SSticker && GAMEMODE_IS_CULT))
- var/text = "The cultists were:"
+ var/text = "The cultists were:"
for(var/datum/mind/cultist in cult)
text += " [cultist.key] was [cultist.name] ("
diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm
index 375a02251bc..0f637153f6c 100644
--- a/code/game/gamemodes/cult/cult_comms.dm
+++ b/code/game/gamemodes/cult/cult_comms.dm
@@ -23,8 +23,8 @@
if(!message)
return
- if((user.disabilities & MUTE) || user.mind.miming) //Under vow of silence/mute?
- user.visible_message("[user] appears to whisper to themselves.","You begin to whisper to yourself.") //Make them do *something* abnormal.
+ if((MUTE in user.mutations) || user.mind.miming) //Under vow of silence/mute?
+ user.visible_message("[user] appears to whisper to [user.p_them()]self.","You begin to whisper to yourself.") //Make them do *something* abnormal.
else
user.whisper("O bidai nabora se[pick("'","`")]sma!") // Otherwise book club sayings.
sleep(10)
@@ -32,11 +32,11 @@
if(!user)
return
- if(!((user.disabilities & MUTE) || user.mind.miming)) // If they aren't mute/miming, commence the whisperting
+ if(!((MUTE in user.mutations) || user.mind.miming)) // If they aren't mute/miming, commence the whisperting
user.whisper(message)
var/my_message
- if(istype(user, /mob/living/simple_animal/slaughter/cult)) //Harbringers of the Slaughter
- my_message = "Harbringer of the Slaughter: [message]"
+ if(istype(user, /mob/living/simple_animal/slaughter/cult)) //Harbingers of the Slaughter
+ my_message = "Harbinger of the Slaughter: [message]"
else
my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [user.real_name]: [message]"
for(var/mob/M in GLOB.player_list)
@@ -46,3 +46,4 @@
to_chat(M, "(F) [my_message] ")
log_say("(CULT) [message]", user)
+ user.create_log(SAY_LOG, "(CULT) [message]")
diff --git a/code/game/gamemodes/cult/cult_datums.dm b/code/game/gamemodes/cult/cult_datums.dm
index 825f0c32f3b..73c7dc2cf03 100644
--- a/code/game/gamemodes/cult/cult_datums.dm
+++ b/code/game/gamemodes/cult/cult_datums.dm
@@ -72,36 +72,60 @@
/datum/cult_info/fire
- name = "Cult of Pyr'Kaeus"
+ name = "Cult of Kha'Rin"
theme = "fire"
- tome_icon = "firetome"
+ tome_icon = "helltome"
- entity_name = "Pyr'Kaeus"
+ entity_name = "Kha'Rin"
entity_title1 = "The Burning One"
entity_title2 = "The One Who Consumes"
entity_title3 = "The Harbinger of Fire"
- entity_icon_state = "narbee"
+ entity_icon_state = "kha'rin"
+ entity_spawn_animation = "kha'rin_spawn_anim"
- cult_wall_icon_state = "firecult"
- cult_floor_icon_state = "cultfire"
+ cult_wall_icon_state = "hellcult"
+ cult_floor_icon_state = "culthell"
+ cult_girder_icon_state = "hell_girder"
- artificer_name = "Igniting Ember"
- artificer_icon_state = "fireartificer"
+ artificer_name = "Summoner"
+ artificer_icon_state = "summoner"
- behemoth_name = "Devouring Hatred"
- behemoth_icon_state = "firejuggernaut"
+ behemoth_name = "Incarnation of Pain"
+ behemoth_icon_state = "incarnation_of_pain"
- wraith_name = "Living Flame"
- wraith_icon_state = "firewraith"
+ wraith_name = "Hell Knight"
+ wraith_icon_state = "hell_knight"
+ wraith_jaunt_out_animation = "infernal_rift_out"
+ wraith_jaunt_in_animation = "infernal_rift_in"
- juggernaut_name = "Pyre Armor"
- juggernaut_icon_state = "firejuggernaut"
+ juggernaut_name = "Incarnation of Pain"
+ juggernaut_icon_state = "incarnation_of_pain"
- harvester_name = "Coal Seeker"//or nipple pincher...
- harvester_icon_state = "fireharvester"
+ harvester_name = "Lost Soul"
+ harvester_icon_state = "lost_soul"
- shade_name = "Charred Soul"
- shade_icon_state = "shade"
+ shade_name = "Ifrit"
+ shade_icon_state = "ifrit"
+
+ pylon_icon_state = "hell_pylon"
+ pylon_icon_state_off = "hell_pylon_off"
+
+ forge_icon_state = "hell_forge"
+ forge_icon_state_off = "hell_forge_off"
+
+ altar_icon_state = "hell_altar"
+ altar_icon_state_off = "hell_altar_off"
+
+ archives_icon_state = "hell_archives"
+ archives_icon_state_off = "hell_archives_off"
+
+ runed_metal_icon_state = "sheet_runed_hell"
+
+ airlock_runed_icon_file = 'icons/obj/doors/airlocks/cult/runed/hell.dmi'
+ airlock_runed_overlays_file = 'icons/obj/doors/airlocks/cult/runed/hell-overlays.dmi'
+
+ airlock_unruned_icon_file = 'icons/obj/doors/airlocks/cult/unruned/hell.dmi'
+ airlock_unruned_overlays_file = 'icons/obj/doors/airlocks/cult/unruned/hell-overlays.dmi'
/datum/cult_info/death
name = "Cult of Mortality"
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index c0daac2a01a..388b16d71af 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -105,7 +105,7 @@
/obj/item/clothing/suit/magusred
name = "magus robes"
- desc = "A set of armored robes worn by the followers of Nar-Sie"
+ desc = "A set of armored robes worn by the followers of Nar-Sie."
icon_state = "magusred"
item_state = "magusred"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
@@ -132,7 +132,7 @@
/obj/item/clothing/suit/hooded/cultrobes/cult_shield
name = "empowered cultist robe"
- desc = "Empowered garb which creates a powerful shield around the user."
+ desc = "An empowered garb which creates a powerful shield around the user."
icon_state = "cult_armour"
item_state = "cult_armour"
w_class = WEIGHT_CLASS_BULKY
@@ -144,7 +144,7 @@
/obj/item/clothing/head/hooded/cult_hoodie
name = "empowered cultist robe"
- desc = "Empowered garb which creates a powerful shield around the user."
+ desc = "An empowered garb which creates a powerful shield around the user."
icon_state = "cult_hoodalt"
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
body_parts_covered = HEAD
@@ -213,8 +213,8 @@
list_reagents = list("unholywater" = 40)
/obj/item/clothing/glasses/night/cultblind
- desc = "May the master guide you through the darkness and shield you from the light."
name = "zealot's blindfold"
+ desc = "May the master guide you through the darkness and shield you from the light."
icon_state = "blindfold"
item_state = "blindfold"
see_in_dark = 8
@@ -247,7 +247,7 @@
to_chat(user, "We have exhausted our ability to curse the shuttle.")
return
if(locate(/obj/singularity/narsie) in GLOB.poi_list || locate(/mob/living/simple_animal/slaughter/cult) in GLOB.mob_list)
- to_chat(user, "Nar-Sie or his avatars are already on this plane, there is no delaying the end of all things.")
+ to_chat(user, "Nar-Sie or her avatars are already on this plane, there is no delaying the end of all things.")
return
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
@@ -273,7 +273,7 @@
/obj/item/cult_shift
name = "veil shifter"
- desc = "This relic teleports you forward a medium distance."
+ desc = "This relic teleports you forward by a medium distance."
icon = 'icons/obj/cult.dmi'
icon_state ="shifter"
var/uses = 4
@@ -353,7 +353,7 @@
/obj/item/clothing/suit/cultrobesghost
name = "ghostly cult robes"
- desc = "A set of ethreal armored robes worn by the undead followers of a cult."
+ desc = "A set of ethereal armored robes worn by the undead followers of a cult."
icon_state = "cultrobesalt"
item_state = "cultrobesalt"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
index 80b889a5bfb..38bd1919c62 100644
--- a/code/game/gamemodes/cult/cult_objectives.dm
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -27,8 +27,8 @@
explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for [sacrifice_target.p_their()] blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
for(var/datum/mind/cult_mind in cult)
- to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
- cult_mind.memory += "Objective #[current_objective]: [explanation] "
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation] "
/datum/game_mode/cult/proc/bypass_phase()
@@ -89,8 +89,8 @@
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
to_chat(cult_mind.current, "You and your acolytes have completed your task, but this place requires yet more preparation!")
- to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
- cult_mind.memory += "Objective #[current_objective]: [explanation] "
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation] "
message_admins("New Cult Objective: [new_objective]")
log_admin("New Cult Objective: [new_objective]")
@@ -104,8 +104,8 @@
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
to_chat(cult_mind.current, "You and your acolytes suddenly feel the urge to do your best, but survive!")
- to_chat(cult_mind.current, "Objective Survive: [explanation]")
- cult_mind.memory += "Objective Survive: [explanation] "
+ to_chat(cult_mind.current, "Objective Survive: [explanation]")
+ cult_mind.memory += "Objective Survive: [explanation] "
/datum/game_mode/cult/proc/second_phase()
@@ -117,13 +117,13 @@
explanation = "Summon [SSticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(GLOB.summon_spots)] for the ritual to begin."
else
objectives += "slaughter"
- explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(GLOB.summon_spots)] for the ritual to begin."
+ explanation = "Bring the Slaughter via the rune 'Call Forth The Slaughter'. The veil is weak enough in [english_list(GLOB.summon_spots)] for the ritual to begin."
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
to_chat(cult_mind.current, "You and your acolytes have succeeded in preparing the station for the ultimate ritual!")
- to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
- cult_mind.memory += "Objective #[current_objective]: [explanation] "
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation] "
/datum/game_mode/cult/proc/third_phase()
current_objective++
@@ -138,16 +138,16 @@
switch(last_objective)
if("harvest")
- explanation = "[SSticker.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humans in sacrifice."
+ explanation = "[SSticker.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humanoids in sacrifice."
if("hijack")
- explanation = "[SSticker.cultdat.entity_name] wishes for their troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
+ explanation = "[SSticker.cultdat.entity_name] wishes for their troops to start the assault on CentCom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
if("massacre")
- explanation = "[SSticker.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
+ explanation = "[SSticker.cultdat.entity_name] wants to watch you as you massacre the remaining crew on the station (until less than [massacre_target] humans are left alive)."
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
- to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
- cult_mind.memory += "Objective #[current_objective]: [explanation] "
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation] "
message_admins("Last Cult Objective: [last_objective]")
log_admin("Last Cult Objective: [last_objective]")
@@ -155,12 +155,12 @@
/datum/game_mode/cult/proc/get_possible_sac_targets()
var/list/possible_sac_targets = list()
for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD))
+ if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD) && (!player.mind.offstation_role) )
possible_sac_targets += player.mind
if(!possible_sac_targets.len)
//There are no living Unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers
for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(is_secure_level(player.z)) //We can't sacrifice people that are on the centcom z-level
+ if(is_secure_level(player.z) || player.mind.offstation_role) //We can't sacrifice people that are on the centcom z-level or offstation roles
continue
if(player.mind && !(player.mind in cult) && (player.stat != DEAD))//make DAMN sure they are not dead
possible_sac_targets += player.mind
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 618abec4470..0e96dd92062 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -134,7 +134,7 @@
to_chat(user, "You may only dunk carbon-based creatures!")
return 0
if(G.affecting == LAVA_PROOF)
- to_chat(user, "Is immune to the lava!")
+ to_chat(user, "[G.affecting] is immune to lava!")
return 0
if(G.affecting.stat == DEAD)
to_chat(user, "[G.affecting] is dead!")
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 9422ffcc716..823a9a8980e 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -50,7 +50,7 @@
if(iscultist(user) || user.stat == DEAD)
. += "The scriptures of [SSticker.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [SSticker.cultdat.entity_name]."
. += "Striking another cultist with it will purge holy water from them."
- . += "Striking a noncultist, however, will sear their flesh."
+ . += "Striking a non-cultist, however, will sear their flesh."
/obj/item/tome/attack(mob/living/M, mob/living/user)
if(!istype(M))
@@ -67,8 +67,8 @@
return
M.take_organ_damage(0, 15) //Used to be a random between 5 and 20
playsound(M, 'sound/weapons/sear.ogg', 50, 1)
- M.visible_message("[user] strikes [M] with the arcane tome!", \
- "[user] strikes you with the tome, searing your flesh!")
+ M.visible_message("[user] strikes [M] with [src]!", \
+ "[user] strikes you with [src], searing your flesh!")
flick("tome_attack", src)
user.do_attack_animation(M)
add_attack_logs(user, M, "Hit with [src]")
@@ -133,7 +133,7 @@
text += "Blood Boil When invoked, this rune will do a massive amount of damage to all non-cultist viewers, but it will also emit a small explosion upon invocation. \
It requires three invokers.
"
- text += "Leeching When invoked, this rune will transfer lifeforce from the victim to the invoker.
"
+ text += "Leeching When invoked, this rune will transfer life force from the victim to the invoker.
"
text += "Rite of Spectral Manifestation This rune allows you to summon spirits as humanoid fighters. When invoked, a spirit above the rune will be brought to life as a human, wearing nothing, that seeks only to serve you and [SSticker.cultdat.entity_title3]. \
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, all summoned spirits will dissipate, dropping their items to the ground. You may manifest \
@@ -175,7 +175,7 @@
text += "Cult Robes Cult robes are heavily armored robes. These robes are produced by the Talisman of Arming.
"
- text += "Soulstone A soulstone is a simple piece of magic, produced either via the starter talisman or by sacrificing humans. Using it on an unconscious or dead human, or on a Shade, will trap their soul in the stone, allowing its use in construct shells. \
+ text += "Soulstone A soulstone is a simple piece of magic, produced either via the starter talisman or by sacrificing humans. Using it on an unconscious or dead humanoid, or on a Shade, will trap their soul in the stone, allowing its use in construct shells. \
The soul within can also be released as a Shade by using it in-hand.
"
text += "Construct Shell A construct shell is useless on its own, but placing a filled soulstone within it allows you to produce your choice of a Wraith, a Juggernaut, or an Artificer. \
@@ -206,7 +206,7 @@
if(GAMEMODE_IS_CULT)
if(!canbypass)//not an admin-tome, check things
if(!cult_mode.narsie_condition_cleared)
- to_chat(user, "There is still more to do before unleashing [SSticker.cultdat.entity_name] power!")
+ to_chat(user, "There is still more to do before unleashing [SSticker.cultdat.entity_name]'s' power!")
return 0
if(!cult_mode.eldergod)
to_chat(user, "\"I am already here. There is no need to try to summon me now.\"")
@@ -220,14 +220,14 @@
if(!(A in GLOB.summon_spots))
to_chat(user, "[SSticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!")
return 0
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deity's power. It is a long, painful ritual and the crew will be alerted to your presence.", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
else
return 1
else//the game mode is not cult..but we ARE a cultist...ALL ON THE ADMINBUS
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deity's power. It is a long, painful ritual and the crew will be alerted to your presence.", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 290d873bcf3..02cd7b6db65 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -332,10 +332,12 @@ GLOBAL_LIST_EMPTY(teleport_runes)
user.forceMove(get_turf(actual_selected_rune))
var/mob/living/carbon/human/H = user
if(user.z != T.z)
- H.bleed(5)
+ if(istype(H))
+ H.bleed(5)
user.apply_damage(5, BRUTE)
else
- H.bleed(rand(5,10))
+ if(istype(H))
+ H.bleed(rand(5,10))
else
fail_invoke()
@@ -496,7 +498,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
if((istype(I, /obj/item/tome) && iscultist(user)))
- user.visible_message("[user] begins erasing the [src]...", "You begin erasing the [src]...")
+ user.visible_message("[user] begins erasing [src]...", "You begin erasing [src]...")
if(do_after(user, 50, target = src)) //Prevents accidental erasures.
log_game("Summon Narsie rune erased by [key_name(user)] with a tome")
message_admins("[key_name_admin(user)] erased a Narsie rune with a tome")
@@ -532,7 +534,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
/obj/effect/rune/slaughter/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
if((istype(I, /obj/item/tome) && iscultist(user)))
- user.visible_message("[user.name] begins erasing the [src]...", "You begin erasing the [src]...")
+ user.visible_message("[user.name] begins erasing [src]...", "You begin erasing [src]...")
if(do_after(user, 50, target = src)) //Prevents accidental erasures.
log_game("Summon demon rune erased by [key_name(user)] with a tome")
message_admins("[key_name_admin(user)] erased a demon rune with a tome")
@@ -647,7 +649,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
mob_to_revive.Beam(mob_to_sacrifice,icon_state="sendbeam",time=20)
sleep(20)
if(!mob_to_sacrifice || !in_range(mob_to_sacrifice, src))
- mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones")
+ mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones.")
return
mob_to_sacrifice.dust()
if(!mob_to_revive || mob_to_revive.stat != DEAD)
@@ -689,7 +691,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
if(3 to 6)
playsound(E, 'sound/effects/EMPulse.ogg', 50, 1)
for(var/M in invokers)
- to_chat(M, "Your hair stands on end as a shockwave eminates from the rune!")
+ to_chat(M, "Your hair stands on end as a shockwave emanates from the rune!")
if(7 to INFINITY)
playsound(E, 'sound/effects/EMPulse.ogg', 100, 1)
for(var/M in invokers)
@@ -720,7 +722,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
log_game("Astral Communion rune failed - more than one user")
return list()
var/turf/T = get_turf(src)
- if(!user in T.contents)
+ if(!(user in T.contents))
to_chat(user, "You must be standing on top of [src]!")
log_game("Astral Communion rune failed - user not standing on rune")
return list()
@@ -806,6 +808,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
allow_excess_invokers = 1
icon_state = "5"
invoke_damage = 5
+ var/summoning = FALSE
var/summontime = 0
/obj/effect/rune/summon/invoke(var/list/invokers)
@@ -817,6 +820,11 @@ GLOBAL_LIST_EMPTY(teleport_runes)
var/mob/living/cultist_to_summon = input(user, "Who do you wish to call to [src]?", "Followers of [SSticker.cultdat.entity_title3]") as null|anything in cultists
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
+ if(summoning)
+ to_chat(user, "You are already summoning a target!")
+ fail_invoke()
+ return
+
if(!cultist_to_summon)
to_chat(user, "You require a summoning target!")
fail_invoke()
@@ -832,24 +840,27 @@ GLOBAL_LIST_EMPTY(teleport_runes)
fail_invoke()
log_game("Summon Cultist rune failed - target in away mission")
return
- if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers.len < 3)
- to_chat(user, "The summoning of [cultist_to_summon] is being blocked somehow! You need 3 chanters to counter it!")
+ var/hard_summon = (cultist_to_summon.reagents && cultist_to_summon.reagents.has_reagent("holywater")) || cultist_to_summon.restrained()
+ if(hard_summon && invokers.len < 3)
+ to_chat(user, "The summoning of [cultist_to_summon] is being blocked somehow! You need 3 invokers to counter it!")
fail_invoke()
new /obj/effect/temp_visual/cult/sparks(get_turf(cultist_to_summon)) //observer warning
log_game("Summon Cultist rune failed - holywater in target")
return
-
+ summoning = TRUE
..()
- if(cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained())
+ if(hard_summon)
summontime = 20
- if(do_after(user, summontime, target = loc))
+ if(do_after(user, summontime, target = src))
+ summoning = FALSE // Here incase the proc stops after the qdel
cultist_to_summon.visible_message("[cultist_to_summon] suddenly disappears in a flash of red light!", \
"Overwhelming vertigo consumes you as you are hurled through the air!")
visible_message("A foggy shape materializes atop [src] and solidifies into [cultist_to_summon]!")
cultist_to_summon.forceMove(get_turf(src))
qdel(src)
+ summoning = FALSE
//Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby
/obj/effect/rune/blood_boil
@@ -979,7 +990,7 @@ GLOBAL_LIST_EMPTY(teleport_runes)
..()
playsound(src, 'sound/misc/exit_blood.ogg', 50, 1)
- visible_message("A cloud of red mist forms above [src], and from within steps... a man.")
+ visible_message("A cloud of red mist forms above [src], and from within steps... a humanoid shape.")
to_chat(user, "Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely...")
var/obj/machinery/shield/N = new(get_turf(src))
N.name = "Invoker's Shield"
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index e7fb06c1b94..492d128e222 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -4,7 +4,7 @@
var/cultist_name = "talisman"
var/cultist_desc = "A basic talisman. It serves no purpose."
var/invocation = "Naise meam!"
- info = "
"
+ info = "
​
"
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
@@ -61,17 +61,17 @@
/obj/item/paper/talisman/supply/invoke(mob/living/user, successfuluse = 1)
var/dat = list()
- dat += "There are [uses] bloody runes on the parchment. "
- dat += "Please choose the chant to be imbued into the fabric of reality. "
+ dat += "There are [uses] bloody runes on the parchment. "
+ dat += "Please choose the chant to be imbued into the fabric of reality. "
dat += ""
- dat += "N'ath reth sh'yro eth d'raggathnor! - Summons an arcane tome, used to scribe runes and communicate with other cultists. "
- dat += "Bar'tea eas! - Provides 5 runed metal. "
- dat += "Sas'so c'arta forbici! - Allows you to move to a selected teleportation rune. "
- dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range. "
- dat += "Fuu ma'jin! - Allows you to stun a person by attacking them with the talisman. "
- dat += "Kla'atu barada nikt'o! - Two use talisman, first use makes all nearby runes invisible, second use reveals nearby hidden runes. "
- dat += "Kal'om neth! - Summons a soul stone, used to capture the spirits of dead or dying humans. "
- dat += "Daa'ig osk! - Summons a construct shell for use with soulstone-captured souls. It is too large to carry on your person. "
+ dat += "N'ath reth sh'yro eth d'raggathnor! - Summons an arcane tome, used to scribe runes and communicate with other cultists. "
+ dat += "Bar'tea eas! - Provides 5 runed metal. "
+ dat += "Sas'so c'arta forbici! - Allows you to move to a selected teleportation rune. "
+ dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range. "
+ dat += "Fuu ma'jin! - Allows you to stun a person by attacking them with the talisman. "
+ dat += "Kla'atu barada nikt'o! - Two use talisman, first use makes all nearby runes invisible, second use reveals nearby hidden runes. "
+ dat += "Kal'om neth! - Summons a soul stone, used to capture the spirits of dead or dying humans. "
+ dat += "Daa'ig osk! - Summons a construct shell for use with soulstone-captured souls. It is too large to carry on your person. "
var/datum/browser/popup = new(user, "talisman", "", 400, 400)
popup.set_content(jointext(dat, ""))
popup.open()
@@ -290,7 +290,7 @@
/obj/item/paper/talisman/armor/invoke(mob/living/user, successfuluse = 1)
. = ..()
var/mob/living/carbon/human/H = user
- user.visible_message("Otherworldly armor suddenly appears on [user]!", \
+ user.visible_message("Otherworldly equipment suddenly appears on [user]!", \
"You speak the words of the talisman, arming yourself!")
H.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), slot_wear_suit)
@@ -334,14 +334,14 @@
/obj/item/paper/talisman/construction/attack_self(mob/living/user)
if(iscultist(user))
- to_chat(user, "To use this talisman, place it upon a stack of metal sheets or plasteel sheets!.")
+ to_chat(user, "To use this talisman, place it upon a stack of metal sheets or plasteel sheets!")
else
to_chat(user, "You see strange symbols on the paper. Are they supposed to mean something?")
/obj/item/paper/talisman/construction/attack(obj/M,mob/living/user)
if(iscultist(user))
- to_chat(user, "This talisman will only work on a stack of metal sheets or plasteel sheets!!")
+ to_chat(user, "This talisman will only work on a stack of metal sheets or plasteel sheets!")
log_game("Construct talisman failed - not a valid target")
/obj/item/paper/talisman/construction/afterattack(obj/item/stack/sheet/target, mob/user, proximity_flag, click_parameters)
diff --git a/code/game/gamemodes/devil/devil.dm b/code/game/gamemodes/devil/devil.dm
index ab5f5796d2e..06933891ba6 100644
--- a/code/game/gamemodes/devil/devil.dm
+++ b/code/game/gamemodes/devil/devil.dm
@@ -1,4 +1,4 @@
-var/global/list/whiteness = list (
+GLOBAL_LIST_INIT(whiteness, list(
/obj/item/clothing/under/color/white = 2,
/obj/item/clothing/under/rank/bartender = 1,
/obj/item/clothing/under/rank/chef = 1,
@@ -21,7 +21,7 @@ var/global/list/whiteness = list (
/obj/item/clothing/under/noble_clothes = 1,
/obj/item/clothing/under/sl_suit = 1,
/obj/item/clothing/under/burial = 1
-)
+))
@@ -32,9 +32,9 @@ var/global/list/whiteness = list (
var/mob/living/carbon/human/H = attacker
if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = H.w_uniform
- if(whiteness[U.type])
+ if(GLOB.whiteness[U.type])
src.visible_message("[src] seems to have been harmed by the purity of [attacker]'s clothes.", "Unsullied white clothing is disrupting your form.")
- return whiteness[U.type] + 1
+ return GLOB.whiteness[U.type] + 1
if(BANE_TOOLBOX)
if(istype(weapon,/obj/item/storage/toolbox))
src.visible_message("The [weapon] seems unusually robust this time.", "The [weapon] is your unmaking!")
diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm
index dd67ccc0349..74ff27468cc 100644
--- a/code/game/gamemodes/devil/game_mode.dm
+++ b/code/game/gamemodes/devil/game_mode.dm
@@ -17,7 +17,7 @@
to_chat(world,text)
/datum/game_mode/proc/auto_declare_completion_devils()
- /var/text = ""
+ var/text = ""
if(devils.len)
text += " The devils were:"
for(var/D in devils)
diff --git a/code/game/gamemodes/devil/true_devil/inventory.dm b/code/game/gamemodes/devil/true_devil/inventory.dm
index 437203e2e91..3f5446d88bc 100644
--- a/code/game/gamemodes/devil/true_devil/inventory.dm
+++ b/code/game/gamemodes/devil/true_devil/inventory.dm
@@ -5,7 +5,7 @@
return 1
return 0
-/mob/living/carbon/true_devil/update_inv_r_hand(var/update_icons=1)
+/mob/living/carbon/true_devil/update_inv_r_hand()
..()
if(r_hand)
var/t_state = r_hand.item_state
@@ -17,11 +17,10 @@
devil_overlays[DEVIL_R_HAND_LAYER] = I
else
devil_overlays[DEVIL_R_HAND_LAYER] = null
- if(update_icons)
- update_icons()
+ update_icons()
-/mob/living/carbon/true_devil/update_inv_l_hand(var/update_icons=1)
+/mob/living/carbon/true_devil/update_inv_l_hand()
..()
if(l_hand)
var/t_state = l_hand.item_state
@@ -33,8 +32,7 @@
devil_overlays[DEVIL_L_HAND_LAYER] = I
else
devil_overlays[DEVIL_L_HAND_LAYER] = null
- if(update_icons)
- update_icons()
+ update_icons()
/mob/living/carbon/true_devil/proc/remove_overlay(cache_index)
if(devil_overlays[cache_index])
diff --git a/code/game/gamemodes/factions.dm b/code/game/gamemodes/factions.dm
deleted file mode 100644
index 1780881a51d..00000000000
--- a/code/game/gamemodes/factions.dm
+++ /dev/null
@@ -1,97 +0,0 @@
-
-// Normal factions:
-
-/datum/faction
- var/name // the name of the faction
- var/desc // small paragraph explaining the traitor faction
-
- var/list/restricted_species = list() // only members of these species can be recruited.
- var/list/members = list() // a list of mind datums that belong to this faction
- var/max_op = 0 // the maximum number of members a faction can have (0 for no max)
-
-// Factions, members of the syndicate coalition:
-
-/datum/faction/syndicate
-
- var/list/alliances = list() // these alliances work together
- var/list/equipment = list() // associative list of equipment available for this faction and its prices
- var/friendly_identification // 0 to 2, the level of identification of fellow operatives or allied factions
- // 0 - no identification clues
- // 1 - faction gives key words and phrases
- // 2 - faction reveals complete identity/job of other agents
- var/operative_notes // some notes to pass onto each operative
-
- var/uplink_contents // the contents of the uplink
-
-/datum/faction/syndicate/proc/assign_objectives(var/datum/mind/traitor)
- ..()
-
-
-/* ----- Begin defining syndicate factions ------ */
-
-/datum/faction/syndicate/Cybersun_Industries
- name = "Cybersun Industries"
- desc = "Cybersun Industries is a well-known organization that bases its business model primarily on the research and development of human-enhancing computer \
- and mechanical technology. They are notorious for their aggressive corporate tactics, and have been known to subsidize the Gorlex Marauder warlords as a form of paid terrorism. \
- Their competent coverups and unchallenged mind-manipulation and augmentation technology makes them a large threat to Nanotrasen. In the recent years of \
- the syndicate coalition, Cybersun Industries have established themselves as the leaders of the coalition, succeededing the founding group, the Gorlex Marauders."
-
- alliances = list("MI13")
- friendly_identification = 1
- max_op = 3
-
- // Friendly to everyone. (with Tiger Cooperative too, only because they are a member of the coalition. This is the only reason why the Tiger Cooperative are even allowed in the coalition)
-
-/datum/faction/syndicate/Donk
- name = "Donk Corporation"
- desc = "Donk.co is led by a group of ex-pirates, who used to be at a state of all-out war against Waffle.co because of an obscure political scandal, but have recently come to a war limitation. \
- They now consist of a series of colonial governments and companies. They were the first to officially begin confrontations against Nanotrasen because of an incident where \
- Nanotrasen purposely swindled them out of a fortune, sending their controlled colonies into a terrible poverty. Their missions against Nanotrasen \
- revolve around stealing valuables and kidnapping and executing key personnel, ransoming their lives for money. They merged with a splinter-cell of Waffle.co who wanted to end \
- hostilities and formed the Gorlex Marauders."
-
- alliances = list("Gorlex Marauders")
- friendly_identification = 2
- operative_notes = "Most other syndicate operatives are not to be trusted, except fellow Donk members and members of the Gorlex Marauders. We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto. Members of Waffle.co are to be killed on sight; they are not allowed to be on the station while we're around."
-
- // Neutral to everyone, friendly to Marauders
-
-/datum/faction/syndicate/Waffle
- name = "Waffle Corporation"
- desc = "Waffle.co is an interstellar company that produces the best waffles in the galaxy. Their waffles have been rumored to be dipped in the most exotic and addictive \
- drug known to man. They were involved in a political scandal with Donk.co, and have since been in constant war with them. Because of their constant exploits of the galactic \
- economy and stock market, they have been able to bribe their way into amassing a large arsenal of weapons of mass destruction. They target Nanotrasen because of their communistic \
- threat, and their economic threat. Their leaders often have a twisted sense of humor, often misleading and intentionally putting their operatives into harm for laughs.\
- A splinter-cell of Waffle.co merged with Donk.co and formed the Gorlex Marauders and have been a constant ally since. The Waffle.co has lost an overwhelming majority of its military to the Gorlex Marauders."
-
- alliances = list("Gorlex Marauders")
- friendly_identification = 2
- operative_notes = "Most other syndicate operatives are not to be trusted, except for members of the Gorlex Marauders. Do not trust fellow members of the Waffle.co (but try not to rat them out), as they might have been assigned opposing objectives. We encourage humorous terrorism against Nanotrasen; we like to see our operatives creatively kill people while getting the job done."
-
- // Neutral to everyone, friendly to Marauders
-
-
-/* ----- Begin defining miscellaneous factions ------ */
-
-/datum/faction/Wizard
- name = "Wizards Federation"
- desc = "The Wizards Federation is a mysterious organization of magically-talented individuals who act as an equal collective, and have no heirarchy. It is unknown how the wizards \
- are even able to communicate; some suggest a form of telepathic hive-mind. Not much is known about the wizards or their philosphies and motives. They appear to attack random \
- civilian, corporate, planetary, orbital, pretty much any sort of organized facility they come across. Members of the Wizards Federation are considered amongst the most dangerous \
- individuals in the known universe, and have been labeled threats to humanity by most governments. As such, they are enemies of both Nanotrasen and the Syndicate."
-
-/datum/faction/Cult
- name = "The Cult of the Elder Gods"
- desc = "The Cult of the Elder Gods is highly untrusted but otherwise elusive religious organization bent on the revival of the so-called \"Elder Gods\" into the mortal realm. Despite their obvious dangeorus practices, \
- no confirmed reports of violence by members of the Cult have been reported, only rumor and unproven claims. Their nature is unknown, but recent discoveries have hinted to the possibility \
- of being able to de-convert members of this cult through what has been dubbed \"religious warfare\"."
-
-
-// These can maybe be added into a game mode or a mob?
-
-/datum/faction/Exolitics
- name = "Exolitics United"
- desc = "The Exolitics are an ancient alien race with an energy-based anatomy. Their culture, communication, morales and knowledge is unknown. They are so radically different to humans that their \
- attempts of communication with other life forms is completely incomprehensible. Members of this alien race are capable of broadcasting subspace transmissions from their bodies. \
- The religious leaders of the Tiger Cooperative claim to have the technology to decypher and interpret their messages, which have been confirmed as religious propaganda. Their motives are unknown \
- but they are otherwise not considered much of a threat to anyone. They are virtually indestructable because of their nonphysical composition, and have the frighetning ability to make anything stop existing in a second."
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 0981ec72a51..57a77167346 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -164,11 +164,11 @@
if(ishuman(M))
if(!M.stat)
surviving_humans++
- if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
+ if(M.loc && M.loc.loc && (M.loc.loc.type in escape_locations))
escaped_humans++
if(!M.stat)
surviving_total++
- if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
+ if(M.loc && M.loc.loc && (M.loc.loc.type in escape_locations))
escaped_total++
if(M.loc && M.loc.loc && M.loc.loc.type == SSshuttle.emergency.areaInstance.type && SSshuttle.emergency.mode >= SHUTTLE_ENDGAME)
@@ -291,7 +291,8 @@
///////////////////////////////////
/datum/game_mode/proc/get_living_heads()
. = list()
- for(var/mob/living/carbon/human/player in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/player = thing
var/list/real_command_positions = GLOB.command_positions.Copy() - "Nanotrasen Representative"
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in real_command_positions))
. |= player.mind
@@ -312,7 +313,8 @@
//////////////////////////////////////////////
/datum/game_mode/proc/get_living_sec()
. = list()
- for(var/mob/living/carbon/human/player in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/player = thing
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
@@ -321,7 +323,8 @@
////////////////////////////////////////
/datum/game_mode/proc/get_all_sec()
. = list()
- for(var/mob/living/carbon/human/player in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/player = thing
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
@@ -415,7 +418,7 @@ proc/display_roundstart_logout_report()
/proc/get_nuke_code()
var/nukecode = "ERROR"
- for(var/obj/machinery/nuclearbomb/bomb in world)
+ for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
if(bomb && bomb.r_code && is_station_level(bomb.z))
nukecode = bomb.r_code
return nukecode
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index ad15da69412..526a2c01083 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -83,6 +83,36 @@
else
add_ranged_ability(user, enable_text)
+/datum/action/innate/ai/choose_modules
+ name = "Choose Modules"
+ desc = "Spend your processing time to gain a variety of different abilities."
+ button_icon_state = "choose_module"
+ auto_use_uses = FALSE // This is an infinite ability.
+
+/datum/action/innate/ai/choose_modules/Grant(mob/living/L)
+ . = ..()
+ owner_AI.malf_picker = new /datum/module_picker
+
+/datum/action/innate/ai/choose_modules/Trigger()
+ . = ..()
+ owner_AI.malf_picker.use(owner_AI)
+
+/datum/action/innate/ai/return_to_core
+ name = "Return to Main Core"
+ desc = "Leave the APC you are shunted to, and return to your core."
+ icon_icon = 'icons/obj/power.dmi'
+ button_icon_state = "apcemag"
+ auto_use_uses = FALSE // Here just to prevent the "You have X uses remaining" from popping up.
+
+/datum/action/innate/ai/return_to_core/Trigger()
+ . = ..()
+ var/obj/machinery/power/apc/apc = owner_AI.loc
+ if(!istype(apc)) // This shouldn't happen but here for safety.
+ to_chat(src, "You are already in your Main Core.")
+ return
+ apc.malfvacate()
+ qdel(src)
+
//The datum and interface for the malf unlock menu, which lets them choose actions to unlock.
/datum/module_picker
var/temp
@@ -96,13 +126,7 @@
if((AM.power_type && AM.power_type != /datum/action/innate/ai) || AM.upgrade)
possible_modules += AM
-/datum/module_picker/proc/remove_malf_verbs(mob/living/silicon/ai/AI) //Removes all malfunction-related abilities from the target AI.
- for(var/datum/AI_Module/AM in possible_modules)
- for(var/datum/action/A in AI.actions)
- if(istype(A, initial(AM.power_type)))
- qdel(A)
-
-/datum/module_picker/proc/use(user as mob)
+/datum/module_picker/proc/use(mob/user)
var/dat
dat += {"Select use of processing time: (currently #[processing_time] left.)
@@ -186,7 +210,7 @@
var/unlock_sound //Sound played when an ability is unlocked
var/uses
-/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades!
+/datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades!
return
/datum/AI_Module/large //Big, powerful stuff that can only be used once.
@@ -318,7 +342,7 @@
unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage."
unlock_sound = 'sound/items/rped.ogg'
-/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI)
+/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI)
for(var/obj/machinery/porta_turret/turret in GLOB.machines)
var/turf/T = get_turf(turret)
if(is_station_level(T.z))
@@ -652,7 +676,8 @@
button.desc = desc
/datum/action/innate/ai/blackout/Activate()
- for(var/obj/machinery/power/apc/apc in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/apc
if(prob(30 * apc.overload))
apc.overload_lighting()
else
diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm
index 1888d0e4a1d..60de5ba4238 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction.dm
@@ -282,4 +282,4 @@
/datum/game_mode/proc/update_abductor_icons_removed(datum/mind/alien_mind)
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
hud.leave_hud(alien_mind.current)
- set_antag_hud(alien_mind.current, null)
\ No newline at end of file
+ set_antag_hud(alien_mind.current, null)
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index c27b230b3b2..a0519fcbe56 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -25,6 +25,11 @@
var/combat_armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 90, "acid" = 90)
sprite_sheets = null
+/obj/item/clothing/suit/armor/abductor/vest/Initialize(mapload)
+ . = ..()
+ stealth_armor = getArmor(arglist(stealth_armor))
+ combat_armor = getArmor(arglist(combat_armor))
+
/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop()
flags ^= NODROP
if(ismob(loc))
@@ -475,8 +480,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
H.update_inv_r_hand()
/obj/item/abductor_baton/proc/StunAttack(mob/living/L,mob/living/user)
- user.lastattacked = L
- L.lastattacker = user
+ L.lastattacker = user.real_name
+ L.lastattackerckey = user.ckey
L.Stun(7)
L.Weaken(7)
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
index 6e1b4a39d3a..d7354b87c5c 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm
@@ -166,7 +166,6 @@
eject_abductee()
SendBack(H)
return "Specimen braindead - disposed."
- return "ERROR"
/obj/machinery/abductor/experiment/proc/SendBack(mob/living/carbon/human/H)
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index fa797ac929b..750473b1dfa 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -394,7 +394,7 @@
to_chat(src, " You are feeling far too docile to do that.")
return
- var content = ""
+ var/content = ""
content += "
"
@@ -590,8 +590,6 @@
GrantBorerActions()
RemoveInfestActions()
forceMove(get_turf(host))
-
- reset_perspective(null)
machine = null
host.reset_perspective(null)
diff --git a/code/game/gamemodes/miniantags/borer/borer_event.dm b/code/game/gamemodes/miniantags/borer/borer_event.dm
index 245b8fa7b41..f5a3b7aa4af 100644
--- a/code/game/gamemodes/miniantags/borer/borer_event.dm
+++ b/code/game/gamemodes/miniantags/borer/borer_event.dm
@@ -16,7 +16,7 @@
/datum/event/borer_infestation/start()
var/list/vents = list()
- for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
+ for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in SSair.atmos_machinery)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
//Stops cortical borers getting stuck in small networks. See: Security, Virology
if(temp_vent.parent.other_atmosmch.len > 50)
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 65424bf9008..8da5b4468d7 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -61,6 +61,7 @@
icon = 'icons/mob/swarmer.dmi'
desc = "Robotic constructs of unknown design, swarmers seek only to consume materials and replicate themselves indefinitely."
speak_emote = list("tones")
+ bubble_icon = "swarmer"
health = 40
maxHealth = 40
status_flags = CANPUSH
@@ -330,7 +331,7 @@
to_chat(S, "An inhospitable area may be created as a result of destroying this object. Aborting.")
return FALSE
-/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+/obj/machinery/tcomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.")
return FALSE
@@ -362,6 +363,10 @@
to_chat(S, "This cryopod control computer should be preserved, it contains useful items and information about the inhabitants. Aborting.")
return FALSE
+/obj/structure/spacepoddoor/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ to_chat(S, "Disrupting this energy field would overload us. Aborting.")
+ return FALSE
+
/turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(loc, /area/shuttle)
for(var/turf/T in range(1, src))
@@ -421,13 +426,13 @@
return FALSE
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
- . = ..()
var/turf/here = get_turf(src)
for(var/A in here.contents)
var/obj/structure/cable/C = A
if(istype(C))
to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.")
return FALSE
+ return ..()
/obj/item/deactivated_swarmer/IntegrateAmount()
return 50
@@ -604,7 +609,7 @@
if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
playsound(loc,'sound/effects/snap.ogg',50, 1, -1)
L.electrocute_act(0, src, 1, TRUE, TRUE)
- if(isrobot(L) || L.isSynthetic())
+ if(isrobot(L) || ismachineperson(L))
L.Weaken(5)
qdel(src)
..()
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
index d0be68819ae..fbceda6bd94 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
@@ -13,9 +13,9 @@
/datum/event/spawn_swarmer/start()
if(find_swarmer())
return 0
- if(!the_gateway)
+ if(!GLOB.the_gateway)
return 0
- new /obj/effect/mob_spawn/swarmer(get_turf(the_gateway))
+ new /obj/effect/mob_spawn/swarmer(get_turf(GLOB.the_gateway))
/datum/event/spawn_swarmer/proc/find_swarmer()
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index 387cd03aceb..f647ae5a6d1 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -3,6 +3,7 @@
real_name = "Guardian Spirit"
desc = "A mysterious being that stands by it's charge, ever vigilant."
speak_emote = list("intones")
+ bubble_icon = "guardian"
response_help = "passes through"
response_disarm = "flails at"
response_harm = "punches"
@@ -112,7 +113,7 @@
summoner.death()
-/mob/living/simple_animal/hostile/guardian/handle_hud_icons_health()
+/mob/living/simple_animal/hostile/guardian/update_health_hud()
if(summoner)
var/resulthealth
if(iscarbon(summoner))
@@ -121,8 +122,6 @@
resulthealth = round((summoner.health / summoner.maxHealth) * 100)
if(hud_used)
hud_used.guardianhealthdisplay.maptext = "
[resulthealth]%
"
- med_hud_set_health()
- med_hud_set_status()
/mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE) //The spirit is invincible, but passes on damage to the summoner
var/damage = amount * damage_transfer
@@ -164,7 +163,7 @@
if(loc == summoner)
forceMove(get_turf(summoner))
new /obj/effect/temp_visual/guardian/phase(loc)
- src.client.eye = loc
+ reset_perspective()
cooldown = world.time + 30
/mob/living/simple_animal/hostile/guardian/proc/Recall(forced = FALSE)
@@ -182,15 +181,19 @@
input = stripped_input(src, "Please enter a message to tell your summoner.", "Guardian", "")
else
input = message
- if(!input) return
+ if(!input)
+ return
- for(var/mob/M in GLOB.mob_list)
- if(M == summoner)
- to_chat(M, "[src]: [input]")
- log_say("(GUARDIAN to [key_name(M)]) [input]", src)
- else if(M in GLOB.dead_mob_list && M.client && M.stat == DEAD && !isnewplayer(M))
- to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]")
+ // Show the message to the host and to the guardian.
+ to_chat(summoner, "[src]: [input]")
to_chat(src, "[src]: [input]")
+ log_say("(GUARDIAN to [key_name(summoner)]) [input]", src)
+ create_log(SAY_LOG, "GUARDIAN to HOST: [input]", summoner)
+
+ // Show the message to any ghosts/dead players.
+ for(var/mob/M in GLOB.dead_mob_list)
+ if(M && M.client && M.stat == DEAD && !isnewplayer(M))
+ to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]")
//override set to true if message should be passed through instead of going to host communication
/mob/living/simple_animal/hostile/guardian/say(message, override = FALSE)
@@ -208,18 +211,24 @@
set category = "Guardian"
set desc = "Communicate telepathically with your guardian."
var/input = stripped_input(src, "Please enter a message to tell your guardian.", "Message", "")
- if(!input) return
+ if(!input)
+ return
- for(var/mob/M in GLOB.mob_list)
- if(istype(M, /mob/living/simple_animal/hostile/guardian))
- var/mob/living/simple_animal/hostile/guardian/G = M
- if(G.summoner == src)
- to_chat(G, "[src]: [input]")
- log_say("(GUARDIAN to [key_name(G)]) [input]", src)
+ // Find the guardian in our host's contents.
+ var/mob/living/simple_animal/hostile/guardian/G = locate() in contents
+ if(!G)
+ return
- else if(M in GLOB.dead_mob_list && M.client && M.stat == DEAD && !isnewplayer(M))
- to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]")
+ // Show the message to our guardian and to host.
+ to_chat(G, "[src]: [input]")
to_chat(src, "[src]: [input]")
+ log_say("(GUARDIAN to [key_name(G)]) [input]", src)
+ create_log(SAY_LOG, "HOST to GUARDIAN: [input]", G)
+
+ // Show the message to any ghosts/dead players.
+ for(var/mob/M in GLOB.dead_mob_list)
+ if(M && M.client && M.stat == DEAD && !isnewplayer(M))
+ to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]")
/mob/living/proc/guardian_recall()
set name = "Recall Guardian"
@@ -286,7 +295,7 @@
var/name_list = list("Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces")
/obj/item/guardiancreator/attack_self(mob/living/user)
- for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.alive_mob_list)
if(G.summoner == user)
to_chat(user, "You already have a [mob_name]!")
return
@@ -296,11 +305,12 @@
if(used == TRUE)
to_chat(user, "[used_message]")
return
+ used = TRUE // Set this BEFORE the popup to prevent people using the injector more than once, polling ghosts multiple times, and receiving multiple guardians.
var/choice = alert(user, "[confirmation_message]",, "Yes", "No")
if(choice == "No")
to_chat(user, "You decide against using the [name].")
+ used = FALSE
return
- used = TRUE
to_chat(user, "[use_message]")
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_GUARDIAN, 0, 100)
var/mob/dead/observer/theghost = null
diff --git a/code/game/gamemodes/miniantags/guardian/types/fire.dm b/code/game/gamemodes/miniantags/guardian/types/fire.dm
index 09a202afb91..bf8a908e979 100644
--- a/code/game/gamemodes/miniantags/guardian/types/fire.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/fire.dm
@@ -35,7 +35,7 @@
new /obj/effect/hallucination/delusion(target.loc, target, force_kind = "custom", duration = 200, skip_nearby = 0, custom_icon = icon_state, custom_icon_file = icon)
else
if(prob(45))
- if(ismovableatom(target))
+ if(ismovable(target))
var/atom/movable/M = target
if(!M.anchored && M != summoner)
new /obj/effect/temp_visual/guardian/phase/out(get_turf(M))
diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm
index c59f7f87636..c3f8046f0a9 100644
--- a/code/game/gamemodes/miniantags/guardian/types/healer.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm
@@ -51,7 +51,7 @@
if(iscarbon(target))
changeNext_move(CLICK_CD_MELEE)
if(heal_cooldown <= world.time && !stat)
- var/mob/living/carbon/C = target
+ var/mob/living/carbon/human/C = target
C.adjustBruteLoss(-5, robotic=1)
C.adjustFireLoss(-5, robotic=1)
C.adjustOxyLoss(-5)
@@ -65,7 +65,7 @@
if(loc == summoner)
if(toggle)
a_intent = INTENT_HARM
- hud_used.action_intent.icon_state = a_intent;
+ hud_used.action_intent.icon_state = a_intent
speed = 0
damage_transfer = 0.7
if(adminseal)
@@ -76,7 +76,7 @@
toggle = FALSE
else
a_intent = INTENT_HELP
- hud_used.action_intent.icon_state = a_intent;
+ hud_used.action_intent.icon_state = a_intent
speed = 1
damage_transfer = 1
if(adminseal)
@@ -130,7 +130,7 @@
if(beacon) //Check that the beacon still exists and is in a safe place. No instant kills.
if(beacon.air)
var/datum/gas_mixture/Z = beacon.air
- if(Z.oxygen >= 16 && !Z.toxins && Z.carbon_dioxide < 10 && !Z.trace_gases.len)
+ if(Z.oxygen >= 16 && !Z.toxins && Z.carbon_dioxide < 10 && !Z.sleeping_agent)
if((Z.temperature > 270) && (Z.temperature < 360))
var/pressure = Z.return_pressure()
if((pressure > 20) && (pressure < 550))
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index f86f018757e..637ab69bf04 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -16,6 +16,7 @@
var/icon_stun = "revenant_stun"
var/icon_drain = "revenant_draining"
incorporeal_move = 3
+ see_invisible = INVISIBILITY_REVENANT
invisibility = INVISIBILITY_REVENANT
health = INFINITY //Revenants don't use health, they use essence instead
maxHealth = INFINITY
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
index 34bf06f07f7..91ed583efc7 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
@@ -265,8 +265,8 @@
if(!istype(T, /turf/simulated/floor/plating) && !istype(T, /turf/simulated/floor/engine/cult) && istype(T, /turf/simulated/floor) && prob(15))
var/turf/simulated/floor/floor = T
- if(floor.intact)
- floor.builtin_tile.loc = floor
+ if(floor.intact && floor.floor_tile)
+ new floor.floor_tile(floor)
floor.broken = 0
floor.burnt = 0
floor.make_plating(1)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
index 1f902a51806..5e5f0f87a79 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_spawn_event.dm
@@ -26,13 +26,15 @@
var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
player_mind.active = 1
var/list/spawn_locs = list()
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(isturf(L.loc))
switch(L.name)
if("revenantspawn")
spawn_locs += L.loc
if(!spawn_locs) //If we can't find any revenant spawns, try the carp spawns
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(isturf(L.loc))
switch(L.name)
if("carpspawn")
diff --git a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
index ab54f6991b1..ed0a4a908ed 100644
--- a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
+++ b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
@@ -35,8 +35,8 @@
animation.dir = dir
ExtinguishMob()
- if(pulling && bloodcrawl == BLOODCRAWL_EAT)
- if(istype(pulling, /mob/living/))
+ if(pulling && HAS_TRAIT(src, TRAIT_BLOODCRAWL_EAT))
+ if(isliving(pulling))
var/mob/living/victim = pulling
if(victim.stat == CONSCIOUS)
visible_message("[victim] kicks free of [B] just before entering it!")
@@ -76,13 +76,17 @@
adjustToxLoss(-1000)
if(istype(src, /mob/living/simple_animal/slaughter)) //rason, do not want humans to get this
-
var/mob/living/simple_animal/slaughter/demon = src
demon.devoured++
to_chat(kidnapped, "You feel teeth sink into your flesh, and the--")
kidnapped.adjustBruteLoss(1000)
kidnapped.forceMove(src)
demon.consumed_mobs.Add(kidnapped)
+ if(ishuman(kidnapped))
+ var/mob/living/carbon/human/H = kidnapped
+ if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under))
+ var/obj/item/clothing/under/U = H.w_uniform
+ U.sensor_mode = SENSOR_OFF
else
kidnapped.ghostize()
qdel(kidnapped)
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 1f525e93076..d7e53bdae28 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -35,7 +35,6 @@
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/boost = 0
- bloodcrawl = BLOODCRAWL_EAT
var/devoured = 0
@@ -46,8 +45,8 @@
var/gorecooldown = 0
var/vialspawned = FALSE
loot = list(/obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic, /obj/item/organ/internal/heart/demon)
- var/playstyle_string = "You are the Slaughter Demon, a terrible creature from another existence. You have a single desire: To kill. \
- You may Ctrl+Click on blood pools to travel through them, appearing and dissaapearing from the station at will. \
+ var/playstyle_string = "You are the Slaughter Demon, a terrible creature from another existence. You have a single desire: to kill. \
+ You may Ctrl+Click on blood pools to travel through them, appearing and dissapearing from the station at will. \
Pulling a dead or critical mob while you enter a pool will pull them in with you, allowing you to feast. \
You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. "
del_on_death = 1
@@ -59,6 +58,7 @@
/mob/living/simple_animal/slaughter/New()
..()
remove_from_all_data_huds()
+ ADD_TRAIT(src, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
AddSpell(bloodspell)
whisper_action = new()
@@ -111,8 +111,8 @@
// Cult slaughter demon
/mob/living/simple_animal/slaughter/cult //Summoned as part of the cult objective "Bring the Slaughter"
- name = "harbringer of the slaughter"
- real_name = "harbringer of the Slaughter"
+ name = "harbinger of the slaughter"
+ real_name = "harbinger of the Slaughter"
desc = "An awful creature from beyond the realms of madness."
maxHealth = 500
health = 500
@@ -120,14 +120,14 @@
melee_damage_lower = 60
environment_smash = ENVIRONMENT_SMASH_RWALLS //Smashes through EVERYTHING - r-walls included
faction = list("cult")
- playstyle_string = "You are a Harbringer of the Slaughter. Brought forth by the servants of Nar-Sie, you have a single purpose: slaughter the heretics \
+ playstyle_string = "You are a Harbinger of the Slaughter. Brought forth by the servants of Nar-Sie, you have a single purpose: slaughter the heretics \
who do not worship your master. You may use the ability 'Blood Crawl' near a pool of blood to enter it and become incorporeal. Using the ability again near a blood pool will allow you \
to emerge from it. You are fast, powerful, and almost invincible. By dragging a dead or unconscious body into a blood pool with you, you will consume it after a time and fully regain \
- your health. You may use the Sense Victims in your Cultist tab to locate a random, living heretic."
+ your health. You may use the ability 'Sense Victims' in your Cultist tab to locate a random, living heretic."
/obj/effect/proc_holder/spell/targeted/sense_victims
name = "Sense Victims"
- desc = "Sense the location of heratics"
+ desc = "Sense the location of heretics"
charge_max = 0
clothes_req = 0
range = 20
@@ -139,7 +139,7 @@
/obj/effect/proc_holder/spell/targeted/sense_victims/cast(list/targets, mob/user)
var/list/victims = targets
- for(var/mob/living/L in GLOB.living_mob_list)
+ for(var/mob/living/L in GLOB.alive_mob_list)
if(!L.stat && !iscultist(L) && L.key && L != usr)
victims.Add(L)
if(!targets.len)
@@ -171,8 +171,8 @@
var/client/C = M.client
S.key = C.key
- S.mind.assigned_role = "Harbringer of the Slaughter"
- S.mind.special_role = "Harbringer of the Slaughter"
+ S.mind.assigned_role = "Harbinger of the Slaughter"
+ S.mind.special_role = "Harbinger of the Slaughter"
to_chat(S, playstyle_string)
SSticker.mode.add_cultist(S.mind)
var/obj/effect/proc_holder/spell/targeted/sense_victims/SV = new
@@ -247,33 +247,37 @@
user.visible_message("[user] raises [src] to [user.p_their()] mouth and tears into it with [user.p_their()] teeth!", \
"An unnatural hunger consumes you. You raise [src] to your mouth and devour it!")
playsound(user, 'sound/misc/demon_consume.ogg', 50, 1)
- for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
- if(knownspell.type == /obj/effect/proc_holder/spell/bloodcrawl)
- qdel(src)
- return
- if(user.bloodcrawl == 0)
+ // Eating the heart for the first time. Gives basic bloodcrawling. This is the only time we need to insert the heart.
+ if(!HAS_TRAIT(user, TRAIT_BLOODCRAWL))
user.visible_message("[user]'s eyes flare a deep crimson!", \
"You feel a strange power seep into your body... you have absorbed the demon's blood-travelling powers!")
- user.bloodcrawl = BLOODCRAWL
- else if(user.bloodcrawl == BLOODCRAWL)
- to_chat(user, "You feel diffr- CONSUME THEM! ")
- user.bloodcrawl = BLOODCRAWL_EAT
- else
- to_chat(user, "...and you don't feel any different.")
+ ADD_TRAIT(user, TRAIT_BLOODCRAWL, "bloodcrawl")
+ user.drop_item()
+ insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E.
+ return TRUE
- user.drop_item()
- insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E
+ // Eating a 2nd heart. Gives the ability to drag people into blood and eat them.
+ if(HAS_TRAIT(user, TRAIT_BLOODCRAWL))
+ to_chat(user, "You feel differ- CONSUME THEM! ")
+ ADD_TRAIT(user, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
+ qdel(src) // Replacing their demon heart with another demon heart is pointless, just delete this one and return.
+ return TRUE
+
+ // Eating any more than 2 demon hearts does nothing.
+ to_chat(user, "...and you don't feel any different.")
+ qdel(src)
/obj/item/organ/internal/heart/demon/insert(mob/living/carbon/M, special = 0)
- ..()
+ . = ..()
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
/obj/item/organ/internal/heart/demon/remove(mob/living/carbon/M, special = 0)
..()
if(M.mind)
- M.bloodcrawl = 0
+ REMOVE_TRAIT(M, TRAIT_BLOODCRAWL, "bloodcrawl")
+ REMOVE_TRAIT(M, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
/obj/item/organ/internal/heart/demon/Stop()
@@ -308,7 +312,7 @@
if(M.revive())
M.grab_ghost(force = TRUE)
playsound(get_turf(src), feast_sound, 50, 1, -1)
- to_chat(M, "You leave the [src]'s warm embrace, and feel ready to take on the world.")
+ to_chat(M, "You leave [src]'s warm embrace, and feel ready to take on the world.")
..(M)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index ad1146c0bc8..5fed8ae00f4 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -95,7 +95,8 @@ proc/issyndicate(mob/living/M as mob)
var/list/turf/synd_spawn = list()
- for(var/obj/effect/landmark/A in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/A = thing
if(A.name == "Syndicate-Spawn")
synd_spawn += get_turf(A)
qdel(A)
@@ -140,7 +141,7 @@ proc/issyndicate(mob/living/M as mob)
/datum/game_mode/nuclear/proc/scale_telecrystals()
var/danger
danger = GLOB.player_list.len
- while(!IsMultiple(++danger, 10)) //Increments danger up to the nearest multiple of ten
+ while(!ISMULTIPLE(++danger, 10)) //Increments danger up to the nearest multiple of ten
total_tc += danger * NUKESCALINGMODIFIER
@@ -450,7 +451,7 @@ proc/issyndicate(mob/living/M as mob)
if(foecount == GLOB.score_arrested)
GLOB.score_allarrested = 1
- for(var/obj/machinery/nuclearbomb/nuke in world)
+ for(var/obj/machinery/nuclearbomb/nuke in GLOB.machines)
if(nuke.r_code == "Nope") continue
var/turf/T = get_turf(nuke)
var/area/A = T.loc
@@ -491,13 +492,16 @@ proc/issyndicate(mob/living/M as mob)
for(var/datum/mind/M in SSticker.mode.syndicates)
foecount++
- for(var/mob/living/C in world)
+ for(var/mob in GLOB.mob_living_list)
+ var/mob/living/C = mob
if(ishuman(C) || isAI(C) || isrobot(C))
- if(C.stat == 2) continue
- if(!C.client) continue
+ if(C.stat == DEAD)
+ continue
+ if(!C.client)
+ continue
crewcount++
- var/obj/item/disk/nuclear/N = locate() in world
+ var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list
if(istype(N))
var/atom/disk_loc = N.loc
while(!isturf(disk_loc))
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 1dd254fade7..8e38f106cc7 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -51,8 +51,7 @@ GLOBAL_VAR(bomb_set)
GLOB.bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
timeleft = max(timeleft - 2, 0) // 2 seconds per process()
if(timeleft <= 0)
- spawn
- explode()
+ INVOKE_ASYNC(src, .proc/explode)
SSnanoui.update_uis(src)
return
@@ -347,6 +346,9 @@ GLOBAL_VAR(bomb_set)
/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B)
if(timing == -1.0)
return
+ if(timing) //boom
+ INVOKE_ASYNC(src, .proc/explode)
+ return
qdel(src)
/obj/machinery/nuclearbomb/tesla_act(power, explosive)
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index e8f4c22e377..f6e454bd737 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -357,7 +357,8 @@
var/list/name_counts = list()
var/list/names = list()
- for(var/mob/living/carbon/human/H in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
if(!trackable(H))
continue
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 9974ee8305a..0b46264cb33 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -67,7 +67,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/assassinate/check_completion()
if(target && target.current)
- if(target.current.stat == DEAD || iszombie(target))
+ if(target.current.stat == DEAD)
return 1
if(issilicon(target.current) || isbrain(target.current)) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite
return 1
@@ -111,7 +111,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/maroon/check_completion()
if(target && target.current)
- if(target.current.stat == DEAD || iszombie(target))
+ if(target.current.stat == DEAD)
return 1
if(!target.current.ckey)
return 1
@@ -168,7 +168,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
if(!target) //If it's a free objective.
return 1
if(target.current)
- if(target.current.stat == DEAD || iszombie(target))
+ if(target.current.stat == DEAD)
return 0
if(issilicon(target.current))
return 0
@@ -231,7 +231,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return 0
/datum/objective/block
- explanation_text = "Do not allow any lifeforms, be it organic or synthetic to escape on the shuttle alive. AIs, Cyborgs, and pAIs are not considered alive."
+ explanation_text = "Do not allow any lifeforms, be it organic or synthetic to escape on the shuttle alive. AIs, Cyborgs, Maintenance drones, and pAIs are not considered alive."
martyr_compatible = 1
/datum/objective/block/check_completion()
@@ -243,15 +243,14 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return 0
var/area/A = SSshuttle.emergency.areaInstance
- var/list/protected_mobs = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot)
for(var/mob/living/player in GLOB.player_list)
- if(player.type in protected_mobs)
- continue
+ if(issilicon(player))
+ continue // If they're silicon, they're not considered alive, skip them.
if(player.mind && player.stat != DEAD)
if(get_area(player) == A)
- return 0
+ return 0 // If there are any other organic mobs on the shuttle, you failed the objective.
return 1
@@ -263,7 +262,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return 0
if(isbrain(owner.current))
return 0
- if(!owner.current || owner.current.stat == DEAD || iszombie(owner))
+ if(!owner.current || owner.current.stat == DEAD)
return 0
if(SSticker.force_ending) //This one isn't their fault, so lets just assume good faith
return 1
@@ -318,7 +317,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
explanation_text = "Die a glorious death."
/datum/objective/die/check_completion()
- if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || iszombie(owner))
+ if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current))
return 1
if(issilicon(owner.current) && owner.current != owner.original)
return 1
@@ -400,6 +399,9 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
if(!steal_target)
return 1 // Free Objective
+ if(!owner.current)
+ return FALSE
+
var/list/all_items = owner.current.GetAllContents()
for(var/obj/I in all_items)
@@ -476,7 +478,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
n_p++
target_amount = min(target_amount, n_p)
- explanation_text = "Absorb [target_amount] compatible genomes."
+ explanation_text = "Acquire [target_amount] compatible genomes. The 'Extract DNA Sting' can be used to stealthily get genomes without killing somebody."
return target_amount
/datum/objective/absorb/check_completion()
@@ -571,9 +573,10 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
// /vg/; Vox Inviolate for humans :V
/datum/objective/minimize_casualties
explanation_text = "Minimise casualties."
+
/datum/objective/minimize_casualties/check_completion()
- if(owner.kills.len>5) return 0
- return 1
+ return TRUE
+
//Vox heist objectives.
@@ -779,16 +782,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
explanation_text = "Follow the Inviolate. Minimise death and loss of resources."
/datum/objective/heist/inviolate_death/check_completion()
- var/vox_allowed_kills = 3 // The number of people the vox can accidently kill. Mostly a counter to people killing themselves if a raider touches them to force fail.
- var/vox_total_kills = 0
-
- var/datum/game_mode/heist/H = SSticker.mode
- for(var/datum/mind/raider in H.raiders)
- vox_total_kills += raider.kills.len // Kills are listed in the mind; uses this to calculate vox kills
-
- if(vox_total_kills > vox_allowed_kills) return 0
- return 1
-
+ return TRUE
// Traders
// These objectives have no check_completion, they exist only to tell Sol Traders what to aim for.
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 00ce24b6c46..213814d52e8 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -336,7 +336,7 @@
if(head_revolutionaries.len || GAMEMODE_IS_REVOLUTION)
var/num_revs = 0
var/num_survivors = 0
- for(var/mob/living/carbon/survivor in GLOB.living_mob_list)
+ for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
if(survivor.ckey)
num_survivors++
if(survivor.mind)
@@ -385,7 +385,8 @@
if(foecount == GLOB.score_arrested)
GLOB.score_allarrested = 1
- for(var/mob/living/carbon/human/player in world)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/player = thing
if(player.mind)
var/role = player.mind.assigned_role
if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
@@ -415,7 +416,8 @@
for(var/datum/mind/M in SSticker.mode:revolutionaries)
if(M.current && M.current.stat != DEAD)
revcount++
- for(var/mob/living/carbon/human/player in world)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/player = thing
if(player.mind)
var/role = player.mind.assigned_role
if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
@@ -425,7 +427,8 @@
if(player.mind in SSticker.mode.revolutionaries) continue
loycount++
- for(var/mob/living/silicon/X in world)
+ for(var/beepboop in GLOB.silicon_mob_list)
+ var/mob/living/silicon/X = beepboop
if(X.stat != DEAD)
loycount++
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index e91c0d4f150..2e370db5f7a 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -1,5 +1,21 @@
/datum/controller/subsystem/ticker/proc/scoreboard()
+ //Thresholds for Score Ratings
+ #define SINGULARITY_DESERVES_BETTER -3500
+ #define SINGULARITY_FODDER -3000
+ #define ALL_FIRED -2500
+ #define WASTE_OF_OXYGEN -2000
+ #define HEAP_OF_SCUM -1500
+ #define LAB_MONKEYS -1000
+ #define UNDESIREABLES -500
+ #define SERVANTS_OF_SCIENCE 500
+ #define GOOD_BUNCH 1000
+ #define MACHINE_THIRTEEN 1500
+ #define PROMOTIONS_FOR_EVERYONE 2000
+ #define AMBASSADORS_OF_DISCOVERY 3000
+ #define PRIDE_OF_SCIENCE 4000
+ #define NANOTRANSEN_FINEST 5000
+
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
@@ -25,7 +41,8 @@
GLOB.score_deadaipenalty++
GLOB.score_deadcrew++
- for(var/mob/living/carbon/human/I in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/I = thing
if(I.stat == DEAD && is_station_level(I.z))
GLOB.score_deadcrew++
@@ -44,13 +61,14 @@
var/dmg_score = 0
if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME)
- for(var/mob/living/carbon/human/E in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/E = thing
cash_score = 0
dmg_score = 0
var/turf/location = get_turf(E.loc)
var/area/escape_zone = SSshuttle.emergency.areaInstance
- if(E.stat != DEAD && location in escape_zone) // Escapee Scores
+ if(E.stat != DEAD && (location in escape_zone)) // Escapee Scores
cash_score = get_score_container_worth(E)
if(cash_score > GLOB.score_richestcash)
@@ -71,7 +89,8 @@
// Check station's power levels
- for(var/obj/machinery/power/apc/A in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/A = thing
if(!is_station_level(A.z)) continue
for(var/obj/item/stock_parts/cell/C in A.contents)
if(C.charge < 2300)
@@ -92,15 +111,14 @@
// Bonus Modifiers
- //var/traitorwins = score_traitorswon
var/deathpoints = GLOB.score_deadcrew * 25 //done
var/researchpoints = GLOB.score_researchdone * 30
var/eventpoints = GLOB.score_eventsendured * 50
var/escapoints = GLOB.score_escapees * 25 //done
- var/harvests = GLOB.score_stuffharvested * 5 //done
+ var/harvests = GLOB.score_stuffharvested * 5
var/shipping = GLOB.score_stuffshipped * 5
- var/mining = GLOB.score_oremined * 2 //done
- var/meals = GLOB.score_meals * 5 //done, but this only counts cooked meals, not drinks served
+ var/mining = GLOB.score_oremined * 2 //done, might want polishing
+ var/meals = GLOB.score_meals * 5
var/power = GLOB.score_powerloss * 20
var/messpoints
if(GLOB.score_mess != 0)
@@ -120,13 +138,9 @@
GLOB.score_crewscore += 2500
GLOB.score_powerbonus = 1
- if(GLOB.score_mess == 0)
- GLOB.score_crewscore += 3000
- GLOB.score_messbonus = 1
-
GLOB.score_crewscore += meals
- if(GLOB.score_allarrested)
+ if(GLOB.score_allarrested) // This only seems to be implemented for Rev and Nukies. -DaveKorhal
GLOB.score_crewscore *= 3 // This needs to be here for the bonus to be applied properly
@@ -176,26 +190,19 @@
dat += {"
General Statistics
- The Good:
-
- Useful Items Shipped: [GLOB.score_stuffshipped] ([GLOB.score_stuffshipped * 5] Points)
- Hydroponics Harvests: [GLOB.score_stuffharvested] ([GLOB.score_stuffharvested * 5] Points)
- Ore Mined: [GLOB.score_oremined] ([GLOB.score_oremined * 2] Points)
- Refreshments Prepared: [GLOB.score_meals] ([GLOB.score_meals * 5] Points)
- Research Completed: [GLOB.score_researchdone] ([GLOB.score_researchdone * 30] Points) "}
+ The Good
+ Ore Mined: [GLOB.score_oremined] ([GLOB.score_oremined * 2] Points) "}
if(SSshuttle.emergency.mode == SHUTTLE_ENDGAME) dat += "Shuttle Escapees: [GLOB.score_escapees] ([GLOB.score_escapees * 25] Points) "
- dat += {"Random Events Endured: [GLOB.score_eventsendured] ([GLOB.score_eventsendured * 50] Points)
- Whole Station Powered: [GLOB.score_powerbonus ? "Yes" : "No"] ([GLOB.score_powerbonus * 2500] Points)
- Ultra-Clean Station: [GLOB.score_mess ? "No" : "Yes"] ([GLOB.score_messbonus * 3000] Points)
- The bad:
+ dat += {"
+ Whole Station Powered: [GLOB.score_powerbonus ? "Yes" : "No"] ([GLOB.score_powerbonus * 2500] Points)
+ The Bad Dead bodies on Station: [GLOB.score_deadcrew] (-[GLOB.score_deadcrew * 25] Points) Uncleaned Messes: [GLOB.score_mess] (-[GLOB.score_mess] Points) Station Power Issues: [GLOB.score_powerloss] (-[GLOB.score_powerloss * 20] Points)
- Rampant Diseases: [GLOB.score_disease] (-[GLOB.score_disease * 30] Points) AI Destroyed: [GLOB.score_deadaipenalty ? "Yes" : "No"] (-[GLOB.score_deadaipenalty * 250] Points)
- The Weird
+ The Weird Food Eaten: [GLOB.score_foodeaten] bites/sips Times a Clown was Abused: [GLOB.score_clownabuse]
"}
@@ -217,22 +224,36 @@
var/score_rating = "The Aristocrats!"
switch(GLOB.score_crewscore)
- if(-99999 to -50000) score_rating = "Even the Singularity Deserves Better"
- if(-49999 to -5000) score_rating = "Singularity Fodder"
- if(-4999 to -1000) score_rating = "You're All Fired"
- if(-999 to -500) score_rating = "A Waste of Perfectly Good Oxygen"
- if(-499 to -250) score_rating = "A Wretched Heap of Scum and Incompetence"
- if(-249 to -100) score_rating = "Outclassed by Lab Monkeys"
- if(-99 to -21) score_rating = "The Undesirables"
- if(-20 to 20) score_rating = "Ambivalently Average"
- if(21 to 99) score_rating = "Not Bad, but Not Good"
- if(100 to 249) score_rating = "Skillful Servants of Science"
- if(250 to 499) score_rating = "Best of a Good Bunch"
- if(500 to 999) score_rating = "Lean Mean Machine Thirteen"
- if(1000 to 4999) score_rating = "Promotions for Everyone"
- if(5000 to 9999) score_rating = "Ambassadors of Discovery"
- if(10000 to 49999) score_rating = "The Pride of Science Itself"
- if(50000 to INFINITY) score_rating = "Nanotrasen's Finest"
+ if(-99999 to SINGULARITY_DESERVES_BETTER) score_rating = "Even the Singularity Deserves Better"
+ if(SINGULARITY_DESERVES_BETTER+1 to SINGULARITY_FODDER) score_rating = "Singularity Fodder"
+ if(SINGULARITY_FODDER+1 to ALL_FIRED) score_rating = "You're All Fired"
+ if(ALL_FIRED+1 to WASTE_OF_OXYGEN) score_rating = "A Waste of Perfectly Good Oxygen"
+ if(WASTE_OF_OXYGEN+1 to HEAP_OF_SCUM) score_rating = "A Wretched Heap of Scum and Incompetence"
+ if(HEAP_OF_SCUM+1 to LAB_MONKEYS) score_rating = "Outclassed by Lab Monkeys"
+ if(LAB_MONKEYS+1 to UNDESIREABLES) score_rating = "The Undesirables"
+ if(UNDESIREABLES+1 to SERVANTS_OF_SCIENCE-1) score_rating = "Ambivalently Average"
+ if(SERVANTS_OF_SCIENCE to GOOD_BUNCH-1) score_rating = "Skillful Servants of Science"
+ if(GOOD_BUNCH to MACHINE_THIRTEEN-1) score_rating = "Best of a Good Bunch"
+ if(MACHINE_THIRTEEN to PROMOTIONS_FOR_EVERYONE-1) score_rating = "Lean Mean Machine Thirteen"
+ if(PROMOTIONS_FOR_EVERYONE to AMBASSADORS_OF_DISCOVERY-1) score_rating = "Promotions for Everyone"
+ if(AMBASSADORS_OF_DISCOVERY to PRIDE_OF_SCIENCE-1) score_rating = "Ambassadors of Discovery"
+ if(PRIDE_OF_SCIENCE to NANOTRANSEN_FINEST-1) score_rating = "The Pride of Science Itself"
+ if(NANOTRANSEN_FINEST to INFINITY) score_rating = "Nanotrasen's Finest"
dat += "RATING: [score_rating]"
src << browse(dat, "window=roundstats;size=500x600")
+
+ #undef SINGULARITY_DESERVES_BETTER
+ #undef SINGULARITY_FODDER
+ #undef ALL_FIRED
+ #undef WASTE_OF_OXYGEN
+ #undef HEAP_OF_SCUM
+ #undef LAB_MONKEYS
+ #undef UNDESIREABLES
+ #undef SERVANTS_OF_SCIENCE
+ #undef GOOD_BUNCH
+ #undef MACHINE_THIRTEEN
+ #undef PROMOTIONS_FOR_EVERYONE
+ #undef AMBASSADORS_OF_DISCOVERY
+ #undef PRIDE_OF_SCIENCE
+ #undef NANOTRANSEN_FINEST
diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm
index da171113dd0..f6ba6504381 100644
--- a/code/game/gamemodes/setupgame.dm
+++ b/code/game/gamemodes/setupgame.dm
@@ -34,7 +34,7 @@
//message_admins("Assigning DNA blocks:")
// Standard muts
- GLOB.blindblock = getAssignedBlock("BLIND", numsToAssign)
+ GLOB.blindblock = getAssignedBlock("BLINDNESS", numsToAssign)
GLOB.colourblindblock = getAssignedBlock("COLOURBLIND", numsToAssign)
GLOB.deafblock = getAssignedBlock("DEAF", numsToAssign)
GLOB.hulkblock = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS, good=1)
@@ -133,22 +133,6 @@
//testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]")
-/proc/setupfactions()
-
- // Populate the factions list:
- for(var/x in typesof(/datum/faction))
- var/datum/faction/F = new x
- if(!F.name)
- qdel(F)
- continue
- else
- SSticker.factions.Add(F)
- SSticker.availablefactions.Add(F)
-
- // Populate the syndicate coalition:
- for(var/datum/faction/syndicate/S in SSticker.factions)
- SSticker.syndicate_coalition.Add(S)
-
/proc/setupcult()
var/static/datum/cult_info/picked_cult // Only needs to get picked once
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 9cd91817af4..b46bc3c6c51 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -101,7 +101,7 @@ Made by Xhuis
shadowlings--
var/thrall_scaling = round(num_players() / 3)
- required_thralls = Clamp(thrall_scaling, 15, 25)
+ required_thralls = clamp(thrall_scaling, 15, 25)
thrall_ratio = required_thralls / 15
warning_threshold = round(0.66 * required_thralls)
@@ -194,8 +194,8 @@ Made by Xhuis
return 1
var/mob/living/M = thrall_mind.current
if(issilicon(M))
- M.audible_message("[M] lets out a short blip.", \
- "You have been turned into a robot! You are no longer a thrall! Though you try, you cannot remember anything about your servitude...")
+ M.audible_message("[M] lets out a short blip.")
+ to_chat(M, "You have been turned into a robot! You are no longer a thrall! Though you try, you cannot remember anything about your servitude...")
else
M.visible_message("[M] looks like [M.p_their()] mind is [M.p_their()] own again!", \
"A piercing white light floods your eyes. Your mind is your own again! Though you try, you cannot remember anything about the shadowlings or your time \
@@ -244,8 +244,8 @@ Made by Xhuis
ling_mind.RemoveSpell(S)
var/mob/living/M = ling_mind.current
if(issilicon(M))
- M.audible_message("[M] lets out a short blip.", \
- "You have been turned into a robot! You are no longer a shadowling! Though you try, you cannot remember anything about your time as one...")
+ M.audible_message("[M] lets out a short blip.")
+ to_chat(M, "You have been turned into a robot! You are no longer a shadowling! Though you try, you cannot remember anything about your time as one...")
else
M.visible_message("[M] screams and contorts!", \
"THE LIGHT-- YOUR MIND-- BURNS--")
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 37f7296bd4e..27267d2ec02 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -175,7 +175,6 @@
range = -1
include_user = 1
clothes_req = 0
- var/datum/vision_override/vision_path = /datum/vision_override/nightvision
action_icon_state = "darksight"
/obj/effect/proc_holder/spell/targeted/shadow_vision/cast(list/targets, mob/user = usr)
@@ -185,10 +184,10 @@
var/mob/living/carbon/human/H = target
if(!H.vision_type)
to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.")
- H.vision_type = new vision_path
+ H.set_sight(/datum/vision_override/nightvision)
else
to_chat(H, "You return your vision to normal.")
- H.vision_type = null
+ H.set_sight(null)
/obj/effect/proc_holder/spell/targeted/shadow_vision/thrall
desc = "Thrall Darksight"
@@ -375,7 +374,7 @@
to_chat(target, "You focus your telepathic energies abound, harnessing and drawing together the strength of your thralls.")
- for(M in GLOB.living_mob_list)
+ for(M in GLOB.alive_mob_list)
if(is_thrall(M))
thralls++
to_chat(M, "You feel hooks sink into your mind and pull.")
@@ -413,7 +412,7 @@
else if(thralls >= victory_threshold)
to_chat(target, "You are now powerful enough to ascend. Use the Ascendance ability when you are ready. This will kill all of your thralls.")
to_chat(target, "You may find Ascendance in the Shadowling Evolution tab.")
- for(M in GLOB.living_mob_list)
+ for(M in GLOB.alive_mob_list)
if(is_shadow(M))
var/obj/effect/proc_holder/spell/targeted/collective_mind/CM
if(CM in M.mind.spell_list)
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 7896a4aab61..5fc5e1e78cc 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -161,7 +161,8 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
for(var/mob/living/M in orange(7, H))
M.Weaken(10)
to_chat(M, "An immense pressure slams you onto the ground!")
- for(var/obj/machinery/power/apc/A in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/A = thing
A.overload_lighting()
var/mob/living/simple_animal/ascendant_shadowling/A = new /mob/living/simple_animal/ascendant_shadowling(H.loc)
A.announce("VYSHA NERADA YEKHEZET U'RUU!!", 5, 'sound/hallucinations/veryfar_noise.ogg')
diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm
index de9f8fc0eb7..4175883fc1a 100644
--- a/code/game/gamemodes/steal_items.dm
+++ b/code/game/gamemodes/steal_items.dm
@@ -76,12 +76,12 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
/datum/theft_objective/blueprints
name = "the station blueprints"
- typepath = /obj/item/areaeditor/blueprints
+ typepath = /obj/item/areaeditor/blueprints/ce
protected_jobs = list("Chief Engineer")
altitems = list(/obj/item/photo)
/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I)
- if(istype(I, /obj/item/areaeditor/blueprints))
+ if(istype(I, /obj/item/areaeditor/blueprints/ce))
return 1
if(istype(I, /obj/item/photo))
var/obj/item/photo/P = I
@@ -89,11 +89,6 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
return 1
return 0
-/datum/theft_objective/voidsuit
- name = "a nasa voidsuit"
- typepath = /obj/item/clothing/suit/space/nasavoid
- protected_jobs = list("Research Director")
-
/datum/theft_objective/capmedal
name = "the medal of captaincy"
typepath = /obj/item/clothing/accessory/medal/gold/captain
diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm
index 6c22313ef6e..3caf860383d 100644
--- a/code/game/gamemodes/vampire/vampire.dm
+++ b/code/game/gamemodes/vampire/vampire.dm
@@ -227,6 +227,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
if(istype(spell, /obj/effect/proc_holder/spell))
owner.mind.AddSpell(spell)
powers += spell
+ owner.update_sight() // Life updates conditionally, so we need to update sight here in case the vamp gets new vision based on his powers. Maybe one day refactor to be more OOP and on the vampire's ability datum.
/datum/vampire/proc/get_ability(path)
for(var/P in powers)
@@ -244,6 +245,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
powers -= ability
owner.mind.spell_list.Remove(ability)
qdel(ability)
+ owner.update_sight() // Life updates conditionally, so we need to update sight here in case the vamp loses his vision based powers. Maybe one day refactor to be more OOP and on the vampire's ability datum.
/datum/vampire/proc/update_owner(var/mob/living/carbon/human/current) //Called when a vampire gets cloned. This updates vampire.owner to the new body.
if(current.mind && current.mind.vampire && current.mind.vampire.owner && (current.mind.vampire.owner != current))
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index 032bab0b6e8..07c61628337 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -243,7 +243,7 @@
scramble(1, H, 100)
H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species.
H.sync_organ_dna(assimilate = 1)
- H.update_body(0)
+ H.update_body()
H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover.
H.reset_markings() //...Or markings.
H.dna.ResetUIFrom(H)
@@ -354,10 +354,10 @@
var/datum/objective/protect/serve_objective = new
serve_objective.owner = user.mind
serve_objective.target = H.mind
- serve_objective.explanation_text = "You have been Enthralled by [user]. Follow [user.p_their()] every command."
+ serve_objective.explanation_text = "You have been Enthralled by [user.real_name]. Follow [user.p_their()] every command."
H.mind.objectives += serve_objective
- to_chat(H, "You have been Enthralled by [user]. Follow [user.p_their()] every command.")
+ to_chat(H, "You have been Enthralled by [user.real_name]. Follow [user.p_their()] every command.")
to_chat(user, "You have successfully Enthralled [H]. If [H.p_they()] refuse[H.p_s()] to do as you say just adminhelp.")
H.Stun(2)
add_attack_logs(user, H, "Vampire-thralled")
@@ -507,13 +507,13 @@
to_chat(user, "You cannot find darkness to step to.")
return
+ turfs = list(pick(turfs)) // Pick a single turf for the vampire to jump to.
perform(turfs, user = user)
+// `targets` should only ever contain the 1 valid turf we're jumping to, even though its a list, that's just how the cast() proc works.
/obj/effect/proc_holder/spell/vampire/shadowstep/cast(list/targets, mob/user = usr)
spawn(0)
- var/turf/picked = pick(targets)
-
- if(!picked || !isturf(picked))
+ if(!LAZYLEN(targets)) // If for some reason the turf got deleted.
return
var/mob/living/U = user
U.ExtinguishMob()
@@ -525,7 +525,7 @@
animation.alpha = 127
animation.layer = 5
//animation.master = src
- user.forceMove(picked)
+ user.forceMove(targets[1])
spawn(10)
qdel(animation)
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index da7c6d4e1de..a81b12ed041 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -470,7 +470,7 @@ GLOBAL_LIST_EMPTY(multiverse)
M.equip_to_slot_or_del(sword, slot_r_hand)
if("cyborg")
- if(!ismachine(M))
+ if(!ismachineperson(M))
for(var/obj/item/organ/O in M.bodyparts)
O.robotize(make_tough = 1)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
@@ -809,7 +809,7 @@ GLOBAL_LIST_EMPTY(multiverse)
return
return ..()
-/obj/item/voodoo/check_eye(mob/user as mob)
+/obj/item/voodoo/check_eye(mob/user)
if(loc != user)
user.reset_perspective(null)
user.unset_machine()
@@ -866,8 +866,9 @@ GLOBAL_LIST_EMPTY(multiverse)
possible = list()
if(!link)
return
- for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
- if(md5(H.dna.uni_identity) in link.fingerprints)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ if(H.stat != DEAD && (md5(H.dna.uni_identity) in link.fingerprints))
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index 3dbd9211399..82f6d833d16 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -168,4 +168,4 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
if(summon_type == SUMMON_MAGIC)
give_magic(H)
else
- give_guns(H)
\ No newline at end of file
+ give_guns(H)
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 634fc8f5a38..4bda254d930 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -280,7 +280,7 @@
SH.mind.transfer_to(C)
if(iscultist(C))
var/datum/action/innate/cultcomm/CC = new()
- CC.Grant(C) //We have to grant the cult comms again because they're lost during the mind transfer.
+ CC.Grant(C) //We have to grant the cult comms again because they're lost during the mind transfer.
qdel(T)
qdel(SH)
to_chat(C, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.")
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 0dffc0e6159..d0773947c21 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -1,39 +1,37 @@
/datum/spellbook_entry
var/name = "Entry Name"
-
+ var/is_ragin_restricted = FALSE // FALSE if this is buyable on ragin mages, TRUE if it's not.
var/spell_type = null
var/desc = ""
var/category = "Offensive"
var/log_name = "XX" //What it shows up as in logs
var/cost = 2
- var/refundable = 1
- var/surplus = -1 // -1 for infinite, not used by anything atm
+ var/refundable = TRUE
var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
-/datum/spellbook_entry/proc/IsSpellAvailable() // For config prefs / gamemode restrictions - these are round applied
- return 1
-
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user, obj/item/spellbook/book) // Specific circumstances
- if(book.uses= aspell.level_max)
to_chat(user, "This spell cannot be improved further.")
- return 0
+ return FALSE
else
aspell.name = initial(aspell.name)
aspell.spell_level++
- aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min)/ aspell.level_max)
+ aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min) / aspell.level_max)
if(aspell.charge_max < aspell.charge_counter)
aspell.charge_counter = aspell.charge_max
switch(aspell.spell_level)
@@ -51,37 +49,39 @@
aspell.name = "Instant [aspell.name]"
if(aspell.spell_level >= aspell.level_max)
to_chat(user, "This spell cannot be strengthened any further.")
- return 1
+ return TRUE
//No same spell found - just learn it
- feedback_add_details("wizard_spell_learned",log_name)
- user.mind.AddSpell(S)
- to_chat(user, "You have learned [S.name].")
- return 1
+ feedback_add_details("wizard_spell_learned", log_name)
+ user.mind.AddSpell(newspell)
+ to_chat(user, "You have learned [newspell.name].")
+ return TRUE
/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user, obj/item/spellbook/book)
if(!refundable)
- return 0
+ return FALSE
if(!S)
S = new spell_type()
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
- return 1
- return 0
+ return TRUE
+ return FALSE
/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user, obj/item/spellbook/book) //return point value or -1 for failure
var/area/wizard_station/A = locate()
if(!(user in A.contents))
- to_chat(user, "You can only refund spells at the wizard lair")
+ to_chat(user, "You can only refund spells at the wizard lair.")
return -1
- if(!S)
+ if(!S) //This happens when the spell's source is from another spellbook, from loadouts, or adminery, this create a new template temporary spell
S = new spell_type()
var/spell_levels = 0
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
user.mind.spell_list.Remove(aspell)
- QDEL_NULL(S)
- return cost * (spell_levels+1)
+ qdel(aspell)
+ if(S) //If we created a temporary spell above, delete it now.
+ qdel(S)
+ return cost * (spell_levels + 1)
return -1
/datum/spellbook_entry/proc/GetInfo()
@@ -214,12 +214,7 @@
spell_type = /obj/effect/proc_holder/spell/targeted/lichdom
log_name = "LD"
category = "Defensive"
-
-/datum/spellbook_entry/lichdom/IsSpellAvailable()
- if(SSticker.mode.name == "ragin' mages")
- return FALSE
- else
- return TRUE
+ is_ragin_restricted = TRUE
/datum/spellbook_entry/magicm
name = "Magic Missile"
@@ -321,14 +316,7 @@
desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilities to frustrate you."
cost = 0
log_name = "SGH"
-
-/datum/spellbook_entry/summon/ghosts/IsSpellAvailable()
- if(!SSticker.mode) // In case spellbook is placed on map
- return FALSE
- if(SSticker.mode.name == "ragin' mages")
- return FALSE
- else
- return TRUE
+ is_ragin_restricted = TRUE
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
new /datum/event/wizard/ghost()
@@ -341,14 +329,7 @@
name = "Summon Guns"
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. There is a good chance that they will shoot each other first."
log_name = "SG"
-
-/datum/spellbook_entry/summon/guns/IsSpellAvailable()
- if(!SSticker.mode) // In case spellbook is placed on map
- return FALSE
- if(SSticker.mode.name == "ragin' mages")
- return FALSE
- else
- return TRUE
+ is_ragin_restricted = TRUE
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
feedback_add_details("wizard_spell_learned", log_name)
@@ -362,14 +343,7 @@
name = "Summon Magic"
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
log_name = "SU"
-
-/datum/spellbook_entry/summon/magic/IsSpellAvailable()
- if(!SSticker.mode) // In case spellbook is placed on map
- return FALSE
- if(SSticker.mode.name == "ragin' mages")
- return FALSE
- else
- return TRUE
+ is_ragin_restricted = TRUE
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
feedback_add_details("wizard_spell_learned", log_name)
@@ -396,8 +370,6 @@
dat += "[name]"
dat += " Cost:[cost] "
dat += "[desc] "
- if(surplus>=0)
- dat += "[surplus] left. "
return dat
//Artefacts
@@ -448,7 +420,7 @@
//Weapons and Armors
/datum/spellbook_entry/item/battlemage
name = "Battlemage Armour"
- desc = "An ensorceled suit of armour, protected by a powerful shield. The shield can completely negate sixteen attacks before being permanently depleted."
+ desc = "An ensorceled suit of armour, protected by a powerful shield. The shield can completely negate sixteen attacks before being permanently depleted. Despite appearance it is NOT spaceproof."
item_path = /obj/item/clothing/suit/space/hardsuit/shielded/wizard
limit = 1
category = "Weapons and Armors"
@@ -571,6 +543,48 @@
category = "Summons"
limit = 1
+//Spell loadouts datum, list of loadouts is in wizloadouts.dm
+/datum/spellbook_entry/loadout
+ name = "Standard Loadout"
+ cost = 10
+ category = "Standard"
+ refundable = FALSE
+ buy_word = "Summon"
+ var/list/items_path = list()
+ var/list/spells_path = list()
+ var/destroy_spellbook = FALSE //Destroy the spellbook when bought, for loadouts containing non-standard items/spells, otherwise wiz can refund spells
+
+/datum/spellbook_entry/loadout/GetInfo()
+ var/dat = ""
+ dat += "[name]"
+ if(cost > 0)
+ dat += " Cost:[cost] "
+ else
+ dat += " No Cost "
+ dat += "[desc] "
+ return dat
+
+/datum/spellbook_entry/loadout/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
+ if(destroy_spellbook)
+ var/response = alert(user, "The [src] loadout cannot be refunded once bought. Are you sure this is what you want?", "No refunds!", "No", "Yes")
+ if(response == "No")
+ return FALSE
+ to_chat(user, "[book] crumbles to ashes as you acquire its knowledge.")
+ qdel(book)
+ else if(items_path.len)
+ var/response = alert(user, "The [src] loadout contains items that will not be refundable if bought. Are you sure this is what you want?", "No refunds!", "No", "Yes")
+ if(response == "No")
+ return FALSE
+ if(items_path.len)
+ var/obj/item/storage/box/wizard/B = new(src)
+ for(var/path in items_path)
+ new path(B)
+ user.put_in_hands(B)
+ for(var/path in spells_path)
+ var/obj/effect/proc_holder/spell/S = new path()
+ LearnSpell(user, book, S)
+ return TRUE
+
/obj/item/spellbook
name = "spell book"
desc = "The legendary book of spells of the wizard."
@@ -587,19 +601,21 @@
var/mob/living/carbon/human/owner
var/list/datum/spellbook_entry/entries = list()
var/list/categories = list()
- var/list/main_categories = list("Spells", "Magical Items")
+ var/list/main_categories = list("Spells", "Magical Items", "Loadouts")
var/list/spell_categories = list("Offensive", "Defensive", "Mobility", "Assistance", "Rituals")
var/list/item_categories = list("Artefacts", "Weapons and Armors", "Staves", "Summons")
+ var/list/loadout_categories = list("Standard", "Unique")
/obj/item/spellbook/proc/initialize()
- var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon
+ var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - /datum/spellbook_entry/loadout
for(var/T in entry_types)
var/datum/spellbook_entry/E = new T
- if(E.IsSpellAvailable())
- entries |= E
- categories |= E.category
- else
+ if(GAMEMODE_IS_RAGIN_MAGES && E.is_ragin_restricted)
qdel(E)
+ continue
+ entries |= E
+ categories |= E.category
+
main_tab = main_categories[1]
tab = categories[1]
@@ -676,6 +692,12 @@
if("Summons")
dat += "Magical items geared towards bringing in outside forces to aid you.
"
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased. "
+ if("Standard")
+ dat += "These battle-tested spell sets are easy to use and provide good balance between offense and defense.
"
+ dat += "They all cost, and are worth, 10 spell points. You are able to refund any of the spells included as long as you stay in the wizard den. "
+ if("Unique")
+ dat += "These esoteric loadouts usually contain spells or items that cannot be bought elsewhere in this spellbook.
"
+ dat += "Recommended for experienced wizards looking for something new. No refunds once purchased! "
return dat
/obj/item/spellbook/proc/wrap(content)
@@ -720,23 +742,24 @@
cat_dat[main_category] = ""
dat += "
"
var/datum/spellbook_entry/E
@@ -801,6 +824,8 @@
tab = spell_categories[1]
else if(main_tab == "Magical Items")
tab = item_categories[1]
+ else if(main_tab == "Loadouts")
+ tab = loadout_categories[1]
else if(href_list["page"])
tab = sanitize(href_list["page"])
attack_self(H)
@@ -955,7 +980,7 @@
magichead.voicechange = 1 //NEEEEIIGHH
if(!user.unEquip(user.wear_mask))
qdel(user.wear_mask)
- user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
+ user.equip_to_slot_if_possible(magichead, slot_wear_mask, TRUE, TRUE)
qdel(src)
else
to_chat(user, "I say thee neigh")
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 3d07ae173db..a0bb4c349af 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -135,22 +135,31 @@
qdel(wizard_mob.r_store)
qdel(wizard_mob.l_store)
- wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear)
- wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform)
- wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes)
- if(!isplasmaman(wizard_mob)) //handled in the species file for plasmen on the afterjob equip proc for now
- wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit)
+ if(isplasmaman(wizard_mob))
+ wizard_mob.equipOutfit(new /datum/outfit/plasmaman/wizard)
+ wizard_mob.internal = wizard_mob.r_hand
+ wizard_mob.update_action_buttons_icon()
+ else
+ wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head)
+ wizard_mob.dna.species.after_equip_job(null, wizard_mob)
+ wizard_mob.rejuvenate() //fix any damage taken by naked vox/plasmamen/etc while round setups
+ wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit)
wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), slot_back)
- wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), slot_in_backpack)
+ if(wizard_mob.dna.species.speciesbox)
+ wizard_mob.equip_to_slot_or_del(new wizard_mob.dna.species.speciesbox(wizard_mob), slot_in_backpack)
+ else
+ wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), slot_in_backpack)
wizard_mob.equip_to_slot_or_del(new /obj/item/teleportation_scroll(wizard_mob), slot_r_store)
var/obj/item/spellbook/spellbook = new /obj/item/spellbook(wizard_mob)
spellbook.owner = wizard_mob
- wizard_mob.equip_to_slot_or_del(spellbook, slot_r_hand)
+ wizard_mob.equip_to_slot_or_del(spellbook, slot_l_hand)
wizard_mob.faction = list("wizard")
- wizard_mob.dna.species.after_equip_job(null, wizard_mob)
+
to_chat(wizard_mob, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.")
to_chat(wizard_mob, "The spellbook is bound to you, and others cannot use it.")
@@ -158,7 +167,7 @@
wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.")
wizard_mob.update_icons()
wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic
- return 1
+ return TRUE
// Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged
/datum/game_mode/wizard/check_finished()
diff --git a/code/game/gamemodes/wizard/wizloadouts.dm b/code/game/gamemodes/wizard/wizloadouts.dm
new file mode 100644
index 00000000000..c050b27f273
--- /dev/null
+++ b/code/game/gamemodes/wizard/wizloadouts.dm
@@ -0,0 +1,73 @@
+//Contains wizard loadouts and associated unique spells
+
+//Standard loadouts, which are meant to be suggestions for beginners. Should always be worth exactly 10 spell points, and only contain standard wizard spells/items.
+/datum/spellbook_entry/loadout/mutant
+ name = "Offense Focus : Mutant"
+ desc = "A spellset focused around the Mutate spell as its main source of damage, which provides stun protection, laser eyes, and strong punches. \
+ Ethereal Jaunt and Blink provide escape and mobility, while Magic Missile and Disintegrate can be used together for dangerous or key targets. \
+ As this set lacks any form of healing or resurrection, healing items should be acquired from the station, and you should be careful to avoid being hurt in the first place.
\
+ Provides Mutate, Ethereal Jaunt, Blink, Magic Missile, and Disintegrate."
+ log_name = "OM"
+ spells_path = list(/obj/effect/proc_holder/spell/targeted/genetic/mutate, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \
+ /obj/effect/proc_holder/spell/targeted/projectile/magic_missile, /obj/effect/proc_holder/spell/targeted/touch/disintegrate)
+
+/datum/spellbook_entry/loadout/lich
+ name = "Defense Focus : Lich"
+ desc = "This spellset uses the Bind Soul spell to safeguard your life as a lich and allow for more dangerous offensive spells to be used. \
+ Ethereal Jaunt provides escape, Fireball and Rod Form are your offensive spells, and Disable Tech and Greater Forcewall provides utility in disabling sec equipment or blocking their path. \
+ Care should be taken in hiding the item you choose as your phylactery after using Bind Soul, as you cannot revive if it destroyed or too far from your body!
\
+ Provides Bind Soul, Ethereal Jaunt, Fireball, Rod Form, Disable Tech, and Greater Forcewall."
+ log_name = "DL"
+ spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/fireball, \
+ /obj/effect/proc_holder/spell/targeted/rod_form, /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech, /obj/effect/proc_holder/spell/targeted/forcewall/greater)
+ is_ragin_restricted = TRUE
+
+/datum/spellbook_entry/loadout/wands
+ name = "Utility Focus : Wands"
+ desc = "This set contain a Belt of Wands, providing offensive, defensive, and utility wands. Wands have limited charges, but can be partially recharged with the Charge spell included. \
+ Ethereal Jaunt and Blink provide escape and mobility, while Disintegrate and Repulse can be used to annihilate or push away anyone that gets too close to you. \
+ Do not lose any of your wands to the station's crew, as they are extremely deadly even in their hands. Remember that the Revive wand can be used on yourself for a full heal!
\
+ Provides a Belt of Wands, Charge, Ethereal Jaunt, Blink, Repulse, and Disintegrate."
+ log_name = "UW"
+ items_path = list(/obj/item/storage/belt/wands/full)
+ spells_path = list(/obj/effect/proc_holder/spell/targeted/charge, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \
+ /obj/effect/proc_holder/spell/aoe_turf/repulse, /obj/effect/proc_holder/spell/targeted/touch/disintegrate)
+
+//Unique loadouts, which are more gimmicky. Should contain some unique spell or item that separates it from just buying standard wiz spells, and be balanced around a 10 spell point cost.
+/datum/spellbook_entry/loadout/mimewiz
+ name = "Silencio"
+ desc = "...
\
+ Provides Finger Gun and Invisible Greater Wall manuals, Mime Robes, a Cane and Duct Tape, Ethereal Jaunt, Blink, Teleport, Mime Malaise, Knock, and Stop Time."
+ log_name = "SHH"
+ items_path = list(/obj/item/spellbook/oneuse/mime/fingergun, /obj/item/spellbook/oneuse/mime/greaterwall, /obj/item/clothing/suit/wizrobe/mime, /obj/item/clothing/head/wizard/mime, \
+ /obj/item/clothing/mask/gas/mime/wizard, /obj/item/clothing/shoes/sandal/marisa, /obj/item/cane, /obj/item/stack/tape_roll)
+ spells_path = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, /obj/effect/proc_holder/spell/targeted/area_teleport/teleport, \
+ /obj/effect/proc_holder/spell/targeted/touch/mime_malaise, /obj/effect/proc_holder/spell/aoe_turf/knock, /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop)
+ category = "Unique"
+ destroy_spellbook = TRUE
+
+/datum/spellbook_entry/loadout/mimewiz/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
+ if(user.mind)
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null))
+ user.mind.miming = TRUE
+ ..()
+
+/datum/spellbook_entry/loadout/gunreaper
+ name = "Gunslinging Reaper"
+ desc = "Cloned over and over, the souls aboard this station yearn for a deserved rest. \
+ Bring them to the afterlife, one trigger pull at a time. \
+ You will likely need to scavenge additional ammo or weapons aboard the station.
\
+ Provides a .357 Revolver, 4 speedloaders of ammo, Ethereal Jaunt, Blink, Summon Item, No Clothes, and Bind Soul, with a unique outfit."
+ log_name = "GR"
+ items_path = list(/obj/item/gun/projectile/revolver, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/clothing/under/syndicate)
+ spells_path = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \
+ /obj/effect/proc_holder/spell/targeted/summonitem, /obj/effect/proc_holder/spell/noclothes, /obj/effect/proc_holder/spell/targeted/lichdom/gunslinger)
+ category = "Unique"
+ destroy_spellbook = TRUE
+ is_ragin_restricted = TRUE
+
+/obj/effect/proc_holder/spell/targeted/lichdom/gunslinger/equip_lich(mob/living/carbon/human/H)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(H), slot_gloves)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(H), slot_w_uniform)
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 7f93fd9fef6..d5a59a36872 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -20,8 +20,6 @@
else
return check_access_list(acc)
- return 0
-
/obj/item/proc/GetAccess()
return list()
diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm
index 796db23b36e..f91460ba234 100644
--- a/code/game/jobs/job/central.dm
+++ b/code/game/jobs/job/central.dm
@@ -34,6 +34,9 @@
/obj/item/implant/dust
)
backpack = /obj/item/storage/backpack/satchel
+ backpack_contents = list(
+ /obj/item/stamp/centcom = 1,
+ )
box = /obj/item/storage/box/centcomofficer
cybernetic_implants = list(
/obj/item/organ/internal/cyberimp/chest/nutriment/plus
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index ad8f3bf6535..d5c5089c8af 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -12,9 +12,6 @@
var/department_flag = 0
var/department_head = list()
- //Players will be allowed to spawn in as jobs that are set to "Station"
- var/list/faction = list("Station")
-
//How many players can be this job
var/total_positions = 0
@@ -54,6 +51,7 @@
var/disabilities_allowed = 1
var/transfer_allowed = TRUE // If false, ID computer will always discourage transfers to this job, even if player is eligible
+ var/hidden_from_job_prefs = FALSE // if true, job preferences screen never shows this job.
var/admin_only = 0
var/spawn_ert = 0
@@ -172,8 +170,8 @@
if(box && H.dna.species.speciesbox)
box = H.dna.species.speciesbox
- if(allow_loadout && H.client && (H.client.prefs.gear && H.client.prefs.gear.len))
- for(var/gear in H.client.prefs.gear)
+ if(allow_loadout && H.client && (H.client.prefs.loadout_gear && H.client.prefs.loadout_gear.len))
+ for(var/gear in H.client.prefs.loadout_gear)
var/datum/gear/G = GLOB.gear_datums[gear]
if(G)
var/permitted = FALSE
@@ -211,7 +209,7 @@
if(gear_leftovers.len)
for(var/datum/gear/G in gear_leftovers)
- var/atom/placed_in = H.equip_or_collect(G.spawn_item(null, H.client.prefs.gear[G.display_name]))
+ var/atom/placed_in = H.equip_or_collect(G.spawn_item(null, H.client.prefs.loadout_gear[G.display_name]))
if(istype(placed_in))
if(isturf(placed_in))
to_chat(H, "Placing [G.display_name] on [placed_in]!")
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index 259afa12c9e..2d1b091a10d 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -30,7 +30,7 @@
l_ear = /obj/item/radio/headset/heads/cmo
id = /obj/item/card/id/cmo
suit_store = /obj/item/flashlight/pen
- l_hand = /obj/item/storage/firstaid/adv
+ l_hand = /obj/item/storage/firstaid/doctor
pda = /obj/item/pda/heads/cmo
backpack_contents = list(
/obj/item/melee/classic_baton/telescopic = 1
@@ -68,7 +68,7 @@
l_ear = /obj/item/radio/headset/headset_med
id = /obj/item/card/id/medical
suit_store = /obj/item/flashlight/pen
- l_hand = /obj/item/storage/firstaid/adv
+ l_hand = /obj/item/storage/firstaid/doctor
pda = /obj/item/pda/medical
backpack = /obj/item/storage/backpack/medic
@@ -315,4 +315,3 @@
satchel = /obj/item/storage/backpack/satchel_med
dufflebag = /obj/item/storage/backpack/duffel/medical
box = /obj/item/storage/box/engineer
-
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 64e69e89765..a32656598df 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -217,7 +217,7 @@
glasses = /obj/item/clothing/glasses/hud/health/sunglasses
id = /obj/item/card/id/security
suit_store = /obj/item/flashlight/pen
- l_hand = /obj/item/storage/firstaid/adv
+ l_hand = /obj/item/storage/firstaid/doctor
pda = /obj/item/pda/medical
implants = list(/obj/item/implant/mindshield)
backpack = /obj/item/storage/backpack/medic
diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm
index b6321765861..fef9c2302b3 100644
--- a/code/game/jobs/job/silicon.dm
+++ b/code/game/jobs/job/silicon.dm
@@ -24,15 +24,15 @@
title = "Cyborg"
flag = JOB_CYBORG
department_flag = JOBCAT_ENGSEC
- total_positions = 1
- spawn_positions = 1
+ total_positions = 2
+ spawn_positions = 2
supervisors = "your laws and the AI" //Nodrak
department_head = list("AI")
selection_color = "#ddffdd"
minimal_player_age = 21
exp_requirements = 300
exp_type = EXP_TYPE_CREW
- alt_titles = list("Android", "Robot")
+ alt_titles = list("Robot")
/datum/job/cyborg/equip(mob/living/carbon/human/H)
if(!H)
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index c56d27bb408..1d627f131b2 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -223,6 +223,7 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
id = /obj/item/card/id/nanotrasen
l_pocket = /obj/item/flash
+ r_pocket = /obj/item/clothing/accessory/lawyers_badge
pda = /obj/item/pda/heads/magistrate
backpack_contents = list(
/obj/item/melee/classic_baton/telescopic = 1
@@ -262,9 +263,12 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
glasses = /obj/item/clothing/glasses/hud/security/sunglasses/read_only
id = /obj/item/card/id/security
l_pocket = /obj/item/laser_pointer
- r_pocket = /obj/item/flash
+ r_pocket = /obj/item/clothing/accessory/lawyers_badge
l_hand = /obj/item/storage/briefcase
pda = /obj/item/pda/lawyer
+ backpack_contents = list(
+ /obj/item/flash = 1
+ )
implants = list(/obj/item/implant/mindshield)
satchel = /obj/item/storage/backpack/satchel_sec
dufflebag = /obj/item/storage/backpack/duffel/security
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index d0064300b62..09328865b59 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -282,14 +282,14 @@
if(visualsOnly)
return
- if(ismachine(H))
+ if(ismachineperson(H))
var/obj/item/organ/internal/cyberimp/brain/clown_voice/implant = new
implant.insert(H)
H.dna.SetSEState(GLOB.clumsyblock, TRUE)
genemutcheck(H, GLOB.clumsyblock, null, MUTCHK_FORCED)
H.dna.default_blocks.Add(GLOB.clumsyblock)
- if(!ismachine(H))
+ if(!ismachineperson(H))
H.dna.SetSEState(GLOB.comicblock, TRUE)
genemutcheck(H, GLOB.comicblock, null, MUTCHK_FORCED)
H.dna.default_blocks.Add(GLOB.comicblock)
@@ -450,3 +450,24 @@
/obj/item/storage/box/lip_stick = 1,
/obj/item/storage/box/barber = 1
)
+
+/datum/job/explorer
+ title = "Explorer"
+ flag = JOB_EXPLORER
+ department_flag = JOBCAT_SUPPORT
+ total_positions = 0
+ spawn_positions = 0
+ supervisors = "the head of personnel"
+ selection_color = "#dddddd"
+ access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS)
+ minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS)
+ outfit = /datum/outfit/job/explorer
+ hidden_from_job_prefs = TRUE
+
+/datum/outfit/job/explorer
+ // This outfit is never used, because there are no slots for this job.
+ // To get it, you have to go to the HOP and ask for a transfer to it.
+ name = "Explorer"
+ jobtype = /datum/job/explorer
+ uniform = /obj/item/clothing/under/color/random
+ shoes = /obj/item/clothing/shoes/black
diff --git a/code/game/jobs/job_scaling.dm b/code/game/jobs/job_scaling.dm
deleted file mode 100644
index c062fe6c216..00000000000
--- a/code/game/jobs/job_scaling.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/hook/roundstart/proc/jobscaling()
- sleep(10 SECONDS) // give everyone time to finish spawning, and the lag to die down
- var/playercount = length(GLOB.clients)
- var/highpop_trigger = 80
-
- if(playercount >= highpop_trigger)
- log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config");
- SSjobs.LoadJobs("config/jobs_highpop.txt")
- else
- log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config");
- return 1
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 8ff6b58e5c4..81cc54aa3c3 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -58,7 +58,8 @@ GLOBAL_LIST_INIT(support_positions, list(
"Barber",
"Magistrate",
"Nanotrasen Representative",
- "Blueshield"
+ "Blueshield",
+ "Explorer"
))
GLOBAL_LIST_INIT(supply_positions, list(
diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm
index ab1bd3b8067..46b98ce1030 100644
--- a/code/game/jobs/whitelist.dm
+++ b/code/game/jobs/whitelist.dm
@@ -2,10 +2,11 @@
GLOBAL_LIST_EMPTY(whitelist)
-/hook/startup/proc/loadWhitelist()
+/proc/init_whitelists()
if(config.usewhitelist)
load_whitelist()
- return 1
+ if(config.usealienwhitelist)
+ load_alienwhitelist()
/proc/load_whitelist()
GLOB.whitelist = file2list(WHITELISTFILE)
@@ -48,11 +49,6 @@ GLOBAL_LIST_EMPTY(whitelist)
GLOBAL_LIST_EMPTY(alien_whitelist)
-/hook/startup/proc/loadAlienWhitelist()
- if(config.usealienwhitelist)
- load_alienwhitelist()
- return 1
-
/proc/load_alienwhitelist()
var/text = file2text("config/alienwhitelist.txt")
if(!text)
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 7317099b8dc..3bcb9675c50 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -136,7 +136,7 @@
/obj/machinery/optable/wrench_act(mob/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(I.use_tool(src, user, 20, volume = I.tool_volume))
to_chat(user, "You deconstruct the table.")
diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm
index 3185cdcddd4..332df41f086 100644
--- a/code/game/machinery/PDApainter.dm
+++ b/code/game/machinery/PDApainter.dm
@@ -30,15 +30,11 @@
/obj/machinery/pdapainter/New()
..()
var/blocked = list(/obj/item/pda/silicon/ai, /obj/item/pda/silicon/robot, /obj/item/pda/silicon/pai, /obj/item/pda/heads,
- /obj/item/pda/clear, /obj/item/pda/syndicate)
+ /obj/item/pda/clear, /obj/item/pda/syndicate, /obj/item/pda/chameleon, /obj/item/pda/chameleon/broken)
- for(var/P in typesof(/obj/item/pda)-blocked)
- var/obj/item/pda/D = new P
-
- //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA"
- D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works.
-
- src.colorlist += D
+ for(var/thing in typesof(/obj/item/pda) - blocked)
+ var/obj/item/pda/P = thing
+ colorlist[initial(P.icon_state)] = initial(P.desc)
/obj/machinery/pdapainter/Destroy()
QDEL_NULL(storedpda)
@@ -104,8 +100,8 @@
if(!in_range(src, user))
return
- storedpda.icon_state = P.icon_state
- storedpda.desc = P.desc
+ storedpda.icon_state = P
+ storedpda.desc = colorlist[P]
else
to_chat(user, "The [src] is empty.")
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 81409b5de86..e4d0befa61e 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -23,6 +23,7 @@
var/initial_bin_rating = 1
var/min_health = -25
var/controls_inside = FALSE
+ var/auto_eject_dead = FALSE
idle_power_usage = 1250
active_power_usage = 2500
@@ -81,8 +82,19 @@
go_out()
/obj/machinery/sleeper/process()
- if(filtering > 0)
- if(beaker)
+ for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp
+ if(M == occupant)
+ continue
+ else
+ M.forceMove(loc)
+
+ if(occupant)
+ if(auto_eject_dead && occupant.stat == DEAD)
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 40)
+ go_out()
+ return
+
+ if(filtering > 0 && beaker)
// To prevent runtimes from drawing blood from runtime, and to prevent getting IPC blood.
if(!istype(occupant) || !occupant.dna || (NO_BLOOD in occupant.dna.species.species_traits))
filtering = 0
@@ -94,7 +106,6 @@
occupant.reagents.trans_to(beaker, 3)
occupant.transfer_blood_to(beaker, 1)
- if(occupant)
for(var/A in occupant.reagents.addiction_list)
var/datum/reagent/R = A
@@ -106,12 +117,6 @@
occupant.reagents.addiction_list.Remove(R)
qdel(R)
- for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp
- if(M == occupant)
- continue
- else
- M.forceMove(loc)
-
updateDialog()
return
@@ -201,6 +206,7 @@
data["maxchem"] = max_chem
data["minhealth"] = min_health
data["dialysis"] = filtering
+ data["auto_eject_dead"] = auto_eject_dead
if(beaker)
data["isBeakerLoaded"] = 1
if(beaker.reagents)
@@ -255,12 +261,22 @@
inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"]))
else
to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!")
+
if(href_list["removebeaker"])
remove_beaker()
+
if(href_list["togglefilter"])
toggle_filter()
+
if(href_list["ejectify"])
eject()
+
+ if(href_list["auto_eject_dead_on"])
+ auto_eject_dead = TRUE
+
+ if(href_list["auto_eject_dead_off"])
+ auto_eject_dead = FALSE
+
add_fingerprint(usr)
return 1
@@ -510,7 +526,7 @@
if(panel_open)
to_chat(usr, "Close the maintenance panel first.")
return
- if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other
+ if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
return
if(usr.has_buckled_mobs()) //mob attached to us
to_chat(usr, "[usr] will not fit into [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.")
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 9d96ec94b99..1ee30b6e9d0 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -314,9 +314,9 @@
occupantData["intOrgan"] = intOrganData
- occupantData["blind"] = (occupant.disabilities & BLIND)
- occupantData["colourblind"] = (occupant.disabilities & COLOURBLIND)
- occupantData["nearsighted"] = (occupant.disabilities & NEARSIGHTED)
+ occupantData["blind"] = (BLINDNESS in occupant.mutations)
+ occupantData["colourblind"] = (COLOURBLIND in occupant.mutations)
+ occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations)
data["occupant"] = occupantData
return data
@@ -498,11 +498,11 @@
dat += "
[i.name]
N/A
[i.damage]
[infection]:[mech][dead]
"
dat += ""
dat += "
"
- if(occupant.disabilities & BLIND)
+ if(BLINDNESS in occupant.mutations)
dat += "Cataracts detected. "
- if(occupant.disabilities & COLOURBLIND)
+ if(COLOURBLIND in occupant.mutations)
dat += "Photoreceptor abnormalities detected. "
- if(occupant.disabilities & NEARSIGHTED)
+ if(NEARSIGHTED in occupant.mutations)
dat += "Retinal misalignment detected. "
else
dat += "[src] is empty."
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 02d95278e30..9fda2cfe45c 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -199,8 +199,8 @@
mode = AALARM_MODE_REPLACEMENT
apply_mode()
-/obj/machinery/alarm/New(var/loc, var/dir, var/building = 0)
- ..()
+/obj/machinery/alarm/New(loc, direction, building = 0)
+ . = ..()
GLOB.air_alarms += src
GLOB.air_alarms = sortAtom(GLOB.air_alarms)
@@ -211,12 +211,11 @@
src.loc = loc
if(dir)
- src.dir = dir
+ setDir(direction)
buildstage = 0
wiresexposed = 1
- pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
- pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
+ set_pixel_offsets_from_dir(-24, 24, -24, 24)
update_icon()
return
@@ -251,7 +250,7 @@
/obj/machinery/alarm/proc/master_is_operating()
if(!alarm_area)
- alarm_area = areaMaster
+ alarm_area = get_area(src)
if(!alarm_area)
log_runtime(EXCEPTION("Air alarm /obj/machinery/alarm lacks alarm_area and areaMaster vars during proc/master_is_operating()"), src)
return FALSE
@@ -299,10 +298,7 @@
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
cur_tlv = TLV["other"]
- var/other_moles = 0.0
- for(var/datum/gas/G in environment.trace_gases)
- other_moles+=G.moles
- var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
+ var/other_dangerlevel = cur_tlv.get_danger_level(environment.total_trace_moles() * GET_PP)
cur_tlv = TLV["temperature"]
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
@@ -326,16 +322,18 @@
apply_mode()
-/obj/machinery/alarm/proc/handle_heating_cooling(var/datum/gas_mixture/environment, var/datum/tlv/cur_tlv, var/turf/simulated/location)
+/obj/machinery/alarm/proc/handle_heating_cooling(datum/gas_mixture/environment, datum/tlv/cur_tlv, turf/simulated/location)
cur_tlv = TLV["temperature"]
//Handle temperature adjustment here.
if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature)
//If it goes too far, we should adjust ourselves back before stopping.
if(!cur_tlv.get_danger_level(target_temperature))
+ var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles())
+ if(!gas)
+ return
if(!regulating_temperature)
regulating_temperature = 1
- visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
- "You hear a click and a faint electronic hum.")
+ visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click and a faint electronic hum.")
if(target_temperature > MAX_TEMPERATURE)
target_temperature = MAX_TEMPERATURE
@@ -343,9 +341,8 @@
if(target_temperature < MIN_TEMPERATURE)
target_temperature = MIN_TEMPERATURE
- var/datum/gas_mixture/gas = location.remove_air(0.25*environment.total_moles())
var/heat_capacity = gas.heat_capacity()
- var/energy_used = max( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
+ var/energy_used = max(abs(heat_capacity * (gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
//Use power. Assuming that each power unit represents 1000 watts....
use_power(energy_used/1000, ENVIRON)
@@ -353,16 +350,15 @@
//We need to cool ourselves.
if(heat_capacity)
if(environment.temperature > target_temperature)
- gas.temperature -= energy_used/heat_capacity
+ gas.temperature -= energy_used / heat_capacity
else
- gas.temperature += energy_used/heat_capacity
+ gas.temperature += energy_used / heat_capacity
environment.merge(gas)
if(abs(environment.temperature - target_temperature) <= 0.5)
regulating_temperature = 0
- visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
- "You hear a click as a faint electronic humming stops.")
+ visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click as a faint electronic humming stops.")
/obj/machinery/alarm/update_icon()
if(wiresexposed)
@@ -625,10 +621,8 @@
var/plasma_percent = round(environment.toxins / total * 100, 2)
cur_tlv = TLV["other"]
- var/other_moles = 0.0
- for(var/datum/gas/G in environment.trace_gases)
- other_moles+=G.moles
- var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
+ var/other_moles = environment.total_trace_moles()
+ var/other_dangerlevel = cur_tlv.get_danger_level(other_moles * GET_PP)
cur_tlv = TLV["temperature"]
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
@@ -996,7 +990,7 @@
if(buildstage != AIR_ALARM_BUILDING)
return
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
to_chat(user, "You start prying out the circuit.")
if(!I.use_tool(src, user, 20, volume = I.tool_volume))
diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm
index f0c6a81820f..3f5fbc374a6 100644
--- a/code/game/machinery/atmo_control.dm
+++ b/code/game/machinery/atmo_control.dm
@@ -357,7 +357,7 @@
if(istype(O,/obj/machinery/air_sensor) || istype(O, /obj/machinery/meter))
return O:id_tag in sensors
-/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, link/context)
+/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, context)
sensors[O:id_tag] = reject_bad_name(clean_input(user, "Choose a sensor label:", "Sensor Label"), allow_numbers=1)
return 1
diff --git a/code/game/machinery/atmoalter/area_atmos_computer.dm b/code/game/machinery/atmoalter/area_atmos_computer.dm
index 3d53e130628..d7650d1cb68 100644
--- a/code/game/machinery/atmoalter/area_atmos_computer.dm
+++ b/code/game/machinery/atmoalter/area_atmos_computer.dm
@@ -164,7 +164,7 @@
var/turf/T = get_turf(src)
if(!T.loc) return
var/area/A = get_area(T)
- for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in world )
+ for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in SSair.atmos_machinery)
var/turf/T2 = get_turf(scrubber)
if(T2 && T2.loc)
var/area/A2 = T2.loc
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index d91fba5fa5c..e927415c759 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -417,8 +417,7 @@ update_flag
if(air_contents.toxins > 0)
message_admins("[key_name_admin(usr)] opened a canister that contains plasma in [get_area(src)]! (JMP)")
log_admin("[key_name(usr)] opened a canister that contains plasma at [get_area(src)]: [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))
+ if(air_contents.sleeping_agent > 0)
message_admins("[key_name_admin(usr)] opened a canister that contains N2O in [get_area(src)]! (JMP)")
log_admin("[key_name(usr)] opened a canister that contains N2O at [get_area(src)]: [x], [y], [z]")
investigate_log(logmsg, "atmos")
@@ -533,29 +532,11 @@ update_flag
..()
canister_color["prim"] = "redws"
- var/datum/gas/sleeping_agent/trace_gas = new
- air_contents.trace_gases += trace_gas
- trace_gas.moles = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ air_contents.sleeping_agent = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
src.update_icon()
return 1
-
-//Dirty way to fill room with gas. However it is a bit easier to do than creating some floor/engine/n2o -rastaf0
-/obj/machinery/portable_atmospherics/canister/sleeping_agent/roomfiller/New()
- ..()
- var/datum/gas/sleeping_agent/trace_gas = air_contents.trace_gases[1]
- trace_gas.moles = 9*4000
- spawn(100)
- var/turf/simulated/location = src.loc
- if(istype(src.loc))
- while(!location.air)
- sleep(1000)
- location.assume_air(air_contents)
- air_contents = new
- return 1
-
-
/obj/machinery/portable_atmospherics/canister/nitrogen/New()
..()
diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm
index 0144a7f93c2..4d54b162466 100644
--- a/code/game/machinery/atmoalter/pump.dm
+++ b/code/game/machinery/atmoalter/pump.dm
@@ -167,7 +167,7 @@
if(href_list["pressure_adj"])
var/diff = text2num(href_list["pressure_adj"])
- target_pressure = Clamp(target_pressure+diff, pressuremin, pressuremax)
+ target_pressure = clamp(target_pressure+diff, pressuremin, pressuremax)
update_icon()
src.add_fingerprint(usr)
diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm
index 36e340d1a12..7af7751ff2c 100644
--- a/code/game/machinery/atmoalter/scrubber.dm
+++ b/code/game/machinery/atmoalter/scrubber.dm
@@ -81,17 +81,11 @@
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
- if(removed.trace_gases.len>0)
- for(var/datum/gas/trace_gas in removed.trace_gases)
- if(istype(trace_gas, /datum/gas/sleeping_agent))
- removed.trace_gases -= trace_gas
- filtered_out.trace_gases += trace_gas
+ filtered_out.sleeping_agent = removed.sleeping_agent
+ removed.sleeping_agent = 0
- if(removed.trace_gases.len>0)
- for(var/datum/gas/trace_gas in removed.trace_gases)
- if(istype(trace_gas, /datum/gas/oxygen_agent_b))
- removed.trace_gases -= trace_gas
- filtered_out.trace_gases += trace_gas
+ filtered_out.agent_b = removed.agent_b
+ removed.agent_b = 0
//Remix the resulting gases
air_contents.merge(filtered_out)
@@ -158,7 +152,7 @@
if(href_list["volume_adj"])
var/diff = text2num(href_list["volume_adj"])
- volume_rate = Clamp(volume_rate+diff, minrate, maxrate)
+ volume_rate = clamp(volume_rate+diff, minrate, maxrate)
src.add_fingerprint(usr)
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 78367327a0c..c22922e4d14 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -38,7 +38,7 @@
var/list/categories = list("Tools", "Electronics", "Construction", "Communication", "Security", "Machinery", "Medical", "Miscellaneous", "Dinnerware", "Imported")
/obj/machinery/autolathe/New()
- AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
+ AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
..()
component_parts = list()
component_parts += new /obj/item/circuitboard/autolathe(null)
@@ -66,7 +66,7 @@
/obj/machinery/autolathe/Destroy()
QDEL_NULL(wires)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
@@ -87,7 +87,7 @@
ui.open()
/obj/machinery/autolathe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/data[0]
data["screen"] = screen
data["total_amount"] = materials.total_amount
@@ -138,7 +138,7 @@
/obj/machinery/autolathe/proc/design_cost_data(datum/design/D)
var/list/data = list()
var/coeff = get_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/has_metal = 1
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] / coeff)))
has_metal = 0
@@ -152,7 +152,7 @@
return data
/obj/machinery/autolathe/proc/queue_data(list/data)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/temp_metal = materials.amount(MAT_METAL)
var/temp_glass = materials.amount(MAT_GLASS)
data["processing"] = being_built.len ? get_processing_line() : null
@@ -288,7 +288,7 @@
//multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier
var/multiplier = text2num(href_list["multiplier"])
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(design_last_ordered.maxstack, design_last_ordered.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/design_last_ordered.materials[MAT_METAL]):INFINITY,design_last_ordered.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/design_last_ordered.materials[MAT_GLASS]):INFINITY)
var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack)
@@ -309,13 +309,13 @@
if(href_list["remove_from_queue"])
var/index = text2num(href_list["remove_from_queue"])
- if(isnum(index) && IsInRange(index, 1, queue.len))
+ if(isnum(index) && ISINRANGE(index, 1, queue.len))
remove_from_queue(index)
if(href_list["queue_move"] && href_list["index"])
var/index = text2num(href_list["index"])
var/new_index = index + text2num(href_list["queue_move"])
if(isnum(index) && isnum(new_index))
- if(IsInRange(new_index, 1, queue.len))
+ if(ISINRANGE(new_index, 1, queue.len))
queue.Swap(index,new_index)
if(href_list["clear_queue"])
queue = list()
@@ -342,7 +342,7 @@
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
tot_rating += MB.rating
tot_rating *= 25000
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = tot_rating * 3
for(var/obj/item/stock_parts/manipulator/M in component_parts)
prod_coeff += M.rating - 1
@@ -355,7 +355,7 @@
desc = initial(desc)+"\nIt's building \a [initial(D.name)]."
var/is_stack = ispath(D.build_path, /obj/item/stack)
var/coeff = get_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/metal_cost = D.materials[MAT_METAL]
var/glass_cost = D.materials[MAT_GLASS]
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
@@ -387,7 +387,7 @@
return 0
var/coeff = get_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/metal_amount = materials.amount(MAT_METAL)
if(custom_metal)
metal_amount = custom_metal
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 796d5c552dd..5ec4206734c 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -189,12 +189,12 @@
active = 1
icon_state = "launcheract"
- for(var/obj/machinery/sparker/M in world)
+ for(var/obj/machinery/sparker/M in GLOB.machines)
if(M.id == id)
spawn( 0 )
M.spark()
- for(var/obj/machinery/igniter/M in world)
+ for(var/obj/machinery/igniter/M in GLOB.machines)
if(M.id == id)
use_power(50)
M.on = !( M.on )
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 5bc32a0172e..b66cad8d328 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -34,9 +34,8 @@
var/in_use_lights = 0 // TO BE IMPLEMENTED
var/toggle_sound = 'sound/items/wirecutter.ogg'
-
-/obj/machinery/camera/New()
- ..()
+/obj/machinery/camera/Initialize()
+ . = ..()
wires = new(src)
assembly = new(src)
assembly.state = 4
@@ -45,9 +44,6 @@
GLOB.cameranet.cameras += src
GLOB.cameranet.addCamera(src)
-
-/obj/machinery/camera/Initialize()
- ..()
if(is_station_level(z) && prob(3) && !start_active)
toggle_cam(null, FALSE)
wires.CutAll()
@@ -364,15 +360,12 @@
for(var/obj/machinery/camera/C in oview(4, M))
if(C.can_use()) // check if camera disabled
return C
- break
return null
/proc/near_range_camera(mob/M)
for(var/obj/machinery/camera/C in range(4, M))
if(C.can_use()) // check if camera disabled
return C
- break
-
return null
/obj/machinery/camera/proc/Togglelight(on = FALSE)
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index 0bd241ee0a0..b7ae75cd13f 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -2,8 +2,8 @@
// EMP
-/obj/machinery/camera/emp_proof/New()
- ..()
+/obj/machinery/camera/emp_proof/Initialize()
+ . = ..()
upgradeEmpProof()
// X-RAY
@@ -11,20 +11,20 @@
/obj/machinery/camera/xray
icon_state = "xraycam" // Thanks to Krutchen for the icons.
-/obj/machinery/camera/xray/New()
- ..()
+/obj/machinery/camera/xray/Initialize()
+ . = ..()
upgradeXRay()
// MOTION
-/obj/machinery/camera/motion/New()
- ..()
+/obj/machinery/camera/motion/Initialize()
+ . = ..()
upgradeMotion()
// ALL UPGRADES
-/obj/machinery/camera/all/New()
- ..()
+/obj/machinery/camera/all/Initialize()
+ . = ..()
upgradeEmpProof()
upgradeXRay()
upgradeMotion()
@@ -41,7 +41,7 @@
number = 1
var/area/A = get_area(src)
if(A)
- for(var/obj/machinery/camera/autoname/C in world)
+ for(var/obj/machinery/camera/autoname/C in GLOB.machines)
if(C == src) continue
var/area/CA = get_area(C)
if(CA.type == A.type)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 3aef616eb98..c622b12c94c 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -4,7 +4,19 @@
//Potential replacement for genetics revives or something I dunno (?)
#define CLONE_BIOMASS 150
-#define BIOMASS_MEAT_AMOUNT 50
+
+#define BIOMASS_BASE_AMOUNT 50 // How much biomass a BIOMASSABLE item gives the cloning pod
+
+// Not a comprehensive list: Further PRs should add appropriate items here.
+// Meat as usual, monstermeat covers goliath, xeno, spider, bear meat
+GLOBAL_LIST_INIT(cloner_biomass_items, list(\
+/obj/item/reagent_containers/food/snacks/meat,\
+/obj/item/reagent_containers/food/snacks/monstermeat,
+/obj/item/reagent_containers/food/snacks/carpmeat,
+/obj/item/reagent_containers/food/snacks/salmonmeat,
+/obj/item/reagent_containers/food/snacks/catfishmeat,
+/obj/item/reagent_containers/food/snacks/tofurkey))
+
#define MINIMUM_HEAL_LEVEL 40
#define CLONE_INITIAL_DAMAGE 190
#define BRAIN_INITIAL_DAMAGE 90 // our minds are too feeble for 190
@@ -15,8 +27,9 @@
desc = "An electronically-lockable pod for growing organic tissue."
density = 1
icon = 'icons/obj/cloning.dmi'
- icon_state = "pod_0"
+ icon_state = "pod_idle"
req_access = list(ACCESS_GENETICS) //For premature unlocking.
+
var/mob/living/carbon/human/occupant
var/heal_level //The clone is released once its health reaches this level.
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
@@ -302,13 +315,14 @@
attempting = 0
return 1
-//Grow clones to maturity then kick them out. FREELOADERS
+//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
- var/show_message = 0
- for(var/obj/item/reagent_containers/food/snacks/meat/meat in range(1, src))
- qdel(meat)
- biomass += BIOMASS_MEAT_AMOUNT
- show_message = 1
+ var/show_message = FALSE
+ for(var/obj/item/item in range(1, src))
+ if(is_type_in_list(item, GLOB.cloner_biomass_items))
+ qdel(item)
+ biomass += BIOMASS_BASE_AMOUNT
+ show_message = TRUE
if(show_message)
visible_message("[src] sucks in and processes the nearby biomass.")
@@ -381,11 +395,11 @@
to_chat(user, "You force an emergency ejection.")
go_out()
-//Removing cloning pod biomass
- else if(istype(I, /obj/item/reagent_containers/food/snacks/meat))
+// A user can feed in biomass sources manually.
+ else if(is_type_in_list(I, GLOB.cloner_biomass_items))
if(user.drop_item())
to_chat(user, "[src] processes [I].")
- biomass += BIOMASS_MEAT_AMOUNT
+ biomass += BIOMASS_BASE_AMOUNT
qdel(I)
else
return ..()
@@ -405,7 +419,9 @@
/obj/machinery/clonepod/screwdriver_act(mob/user, obj/item/I)
. = TRUE
- default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I)
+ // These icon states don't really matter since we need to call update_icon() to handle panel open/closed overlays anyway.
+ default_deconstruction_screwdriver(user, null, null, I)
+ update_icon()
/obj/machinery/clonepod/wrench_act(mob/user, obj/item/I)
. = TRUE
@@ -531,11 +547,17 @@
/obj/machinery/clonepod/update_icon()
..()
- icon_state = "pod_0"
+ cut_overlays()
+
+ if(panel_open)
+ add_overlay("panel_open")
+
if(occupant && !(stat & NOPOWER))
- icon_state = "pod_1"
- else if(mess && !panel_open)
- icon_state = "pod_g"
+ icon_state = "pod_cloning"
+ else if(mess)
+ icon_state = "pod_mess"
+ else
+ icon_state = "pod_idle"
/obj/machinery/clonepod/relaymove(mob/user)
if(user.stat == CONSCIOUS)
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index cb5e4da5e95..30538390e8d 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -346,6 +346,22 @@
return
// HOLOFLOOR DOES NOT GIVE A FUCK
+/turf/simulated/floor/holofloor/space
+ name = "\proper space"
+ icon = 'icons/turf/space.dmi'
+ icon_state = "0"
+ plane = PLANE_SPACE
+
+/turf/simulated/floor/holofloor/space/Initialize(mapload)
+ icon_state = SPACE_ICON_STATE // so realistic
+ . = ..()
+
+/turf/simulated/floor/holofloor/space/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/space.dmi'
+ underlay_appearance.icon_state = SPACE_ICON_STATE
+ underlay_appearance.plane = PLANE_SPACE
+ return TRUE
+
/obj/structure/table/holotable
flags = NODECONSTRUCT
canSmoothWith = list(/obj/structure/table/holotable)
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index ba139e50855..44b55ed1d2c 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -153,6 +153,9 @@
to_chat(user, "You screw the circuit board into place.")
state = SCREWED_CORE
if(GLASS_CORE)
+ var/area/R = get_area(src)
+ message_admins("[key_name_admin(usr)] has completed an AI core in [R]: [ADMIN_COORDJMP(loc)].")
+ log_game("[key_name(usr)] has completed an AI core in [R]: [COORD(loc)].")
to_chat(user, "You connect the monitor.")
if(!brain)
var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes"
diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index a8e30eb0979..123cee3ae4e 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -12,7 +12,7 @@ GLOBAL_LIST_EMPTY(minor_air_alarms)
/obj/machinery/computer/atmos_alert/New()
..()
- SSalarms.atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon)
+ SSalarms.atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/.proc/update_icon)
/obj/machinery/computer/atmos_alert/Destroy()
SSalarms.atmosphere_alarm.unregister(src)
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 2f8321b57bb..b502d6e5441 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -45,7 +45,6 @@
var/list/req_components = null
var/powernet = null
var/list/records = null
- var/frame_desc = null
var/contain_parts = 1
toolspeed = 1
usesound = 'sound/items/deconstruct.ogg'
@@ -64,7 +63,7 @@
var/atom/A = B
if(!ispath(A))
continue
- nice_list += list("[req_components[A]] [initial(A.name)]")
+ nice_list += list("[req_components[A]] [initial(A.name)]\s")
. += "Required components: [english_list(nice_list)]."
/obj/item/circuitboard/message_monitor
@@ -296,19 +295,6 @@
name = "Circuit board (Operating Computer)"
build_path = /obj/machinery/computer/operating
origin_tech = "programming=2;biotech=3"
-/obj/item/circuitboard/comm_monitor
- name = "Circuit board (Telecommunications Monitor)"
- build_path = /obj/machinery/computer/telecomms/monitor
- origin_tech = "programming=3;magnets=3;bluespace=2"
-/obj/item/circuitboard/comm_server
- name = "Circuit board (Telecommunications Server Monitor)"
- build_path = /obj/machinery/computer/telecomms/server
- origin_tech = "programming=3;magnets=3;bluespace=2"
-/obj/item/circuitboard/comm_traffic
- name = "Circuitboard (Telecommunications Traffic Control)"
- build_path = /obj/machinery/computer/telecomms/traffic
- origin_tech = "programming=3;magnets=3;bluespace=2"
-
/obj/item/circuitboard/shuttle
name = "circuit board (Shuttle)"
@@ -364,9 +350,6 @@
build_path = /obj/machinery/computer/telescience
origin_tech = "programming=3;bluespace=3;plasmatech=4"
-/obj/item/circuitboard/atmos_automation
- name = "Circuit board (Atmospherics Automation)"
- build_path = /obj/machinery/computer/general_air_control/atmos_automation
/obj/item/circuitboard/large_tank_control
name = "Circuit board (Atmospheric Tank Control)"
build_path = /obj/machinery/computer/general_air_control/large_tank_control
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index c95735507a5..3f8fc080bf8 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -53,6 +53,9 @@
return TRUE
/obj/machinery/computer/security/check_eye(mob/user)
+ if((stat & (NOPOWER|BROKEN)) || user.incapacitated() || !user.has_vision())
+ user.unset_machine()
+ return
if(!(user in watchers))
user.unset_machine()
return
@@ -65,8 +68,6 @@
return
if(!can_access_camera(C, user))
user.unset_machine()
- return
- return 1
/obj/machinery/computer/security/on_unset_machine(mob/user)
watchers.Remove(user)
@@ -302,7 +303,7 @@
T = get_step(T, direct)
console.jump_on_click(src, T)
return
- return ..(n,direct)
+ return ..()
// Other computer monitors.
/obj/machinery/computer/security/telescreen
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index 76242c4a0e4..bc1bfe6135b 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -37,17 +37,14 @@
eyeobj.RemoveImages()
eyeobj.eye_user = null
user.remote_control = null
- user.remote_view = FALSE
current_user = null
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
/obj/machinery/computer/camera_advanced/check_eye(mob/user)
- if((stat & (NOPOWER|BROKEN)) || !Adjacent(user) || !user.has_vision() || user.incapacitated())
+ if((stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || !user.has_vision() || user.incapacitated())
user.unset_machine()
- return 0
- return 1
/obj/machinery/computer/camera_advanced/Destroy()
if(current_user)
@@ -99,8 +96,6 @@
current_user = user
eyeobj.eye_user = user
eyeobj.name = "Camera Eye ([user.name])"
- // This should be able to be excised once the full view refactor rolls out
- user.remote_view = 1
user.remote_control = eyeobj
user.reset_perspective(eyeobj)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index de85ad842b7..8d6c545e0a8 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -25,7 +25,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
/datum/job/ntnavyofficer,
/datum/job/ntspecops,
/datum/job/civilian,
- /datum/job/syndicateofficer
+ /datum/job/syndicateofficer,
+ /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work
)
// Jobs that appear in the list, and you can prioritize, but not open/close slots for
var/list/blacklisted_partial = list(
@@ -51,7 +52,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
//This is used to keep track of opened positions for jobs to allow instant closing
//Assoc array: "JobName" = (int)
- var/list/opened_positions = list();
+ var/list/opened_positions = list()
/obj/machinery/computer/card/proc/is_centcom()
return istype(src, /obj/machinery/computer/card/centcom)
@@ -133,7 +134,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(!istype(id_card))
return ..()
- if(!scan && ACCESS_CHANGE_IDS in id_card.access)
+ if(!scan && (ACCESS_CHANGE_IDS in id_card.access))
user.drop_item()
id_card.loc = src
scan = id_card
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 14a8e2b6ddc..5198a97a88c 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -164,7 +164,7 @@
data["selected_pod"] = "\ref[selected_pod]"
var/list/temprecords[0]
for(var/datum/dna2/record/R in records)
- var tempRealName = R.dna.real_name
+ var/tempRealName = R.dna.real_name
temprecords.Add(list(list("record" = "\ref[R]", "realname" = sanitize(tempRealName))))
data["records"] = temprecords
@@ -359,12 +359,12 @@
if(scan_brain && !can_brainscan())
return
if(isnull(subject) || (!(ishuman(subject))) || (!subject.dna))
- if(isalien(subject))
+ if(isalien(subject))
scantemp = "Error: Xenomorphs are not scannable."
SSnanoui.update_uis(src)
return
// can add more conditions for specific non-human messages here
- else
+ else
scantemp = "Error: Subject species is not scannable."
SSnanoui.update_uis(src)
return
@@ -372,7 +372,7 @@
var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain)
if(istype(Brn))
if(NO_SCAN in Brn.dna.species.species_traits)
- scantemp = "Error: [subject.dna.species.name_plural] are not scannable."
+ scantemp = "Error: [Brn.dna.species.name_plural] are not scannable."
SSnanoui.update_uis(src)
return
if(!subject.get_int_organ(/obj/item/organ/internal/brain))
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 0faaff3af9d..e161891cdbc 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -424,8 +424,6 @@
else
return menu_state
-/proc/enable_prison_shuttle(var/mob/user);
-
/proc/call_shuttle_proc(var/mob/user, var/reason)
if(GLOB.sent_strike_team == 1)
to_chat(user, "Central Command will not allow the shuttle to be called. Consider all contracts terminated.")
@@ -499,7 +497,6 @@
if(!frequency) return
var/datum/signal/status_signal = new
- status_signal.source = src
status_signal.transmission_method = 1
status_signal.data["command"] = command
@@ -507,13 +504,13 @@
if("message")
status_signal.data["msg1"] = data1
status_signal.data["msg2"] = data2
- log_admin("STATUS: [user] set status screen message with [src]: [data1] [data2]")
+ log_admin("STATUS: [user] set status screen message: [data1] [data2]")
//message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
if("alert")
status_signal.data["picture_state"] = data1
spawn(0)
- frequency.post_signal(src, status_signal)
+ frequency.post_signal(null, status_signal)
/obj/machinery/computer/communications/Destroy()
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index aec41c80be3..2ec8611f420 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -135,7 +135,7 @@
/obj/machinery/computer/screwdriver_act(mob/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(circuit && !(flags & NODECONSTRUCT))
if(I.use_tool(src, user, 20, volume = I.tool_volume))
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index a832e2b5d16..d6a1ccdd33c 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -8,7 +8,7 @@
active_power_usage = 500
light_color = LIGHT_COLOR_DARKBLUE
circuit = /obj/item/circuitboard/crew
- var/datum/nano_module/crew_monitor/crew_monitor
+ var/datum/tgui_module/crew_monitor/crew_monitor
/obj/machinery/computer/crew/New()
crew_monitor = new(src)
@@ -20,17 +20,15 @@
/obj/machinery/computer/crew/attack_ai(mob/user)
attack_hand(user)
- ui_interact(user)
-
/obj/machinery/computer/crew/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
- ui_interact(user)
+ tgui_interact(user)
-/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- crew_monitor.ui_interact(user, ui_key, ui, force_open)
+/obj/machinery/computer/crew/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
+ crew_monitor.tgui_interact(user, ui_key, ui, force_open)
/obj/machinery/computer/crew/interact(mob/user)
- crew_monitor.ui_interact(user)
+ crew_monitor.tgui_interact(user)
diff --git a/code/game/machinery/computer/depot.dm b/code/game/machinery/computer/depot.dm
index 62c82d9bd95..f2e89923eb4 100644
--- a/code/game/machinery/computer/depot.dm
+++ b/code/game/machinery/computer/depot.dm
@@ -165,7 +165,7 @@
alerts_when_broken = TRUE
/obj/machinery/computer/syndicate_depot/selfdestruct/get_menu(mob/user)
- var menutext = {"Syndicate Depot Fusion Reactor Control
+ var/menutext = {"Syndicate Depot Fusion Reactor Control
The new message monitor key is '[server.decryptkey]'. Please keep this a secret and away from the clown. If necessary, change the password to a more secure one."
+ info = "
", buttons)
if("rank")
var/list/L = list("Head of Personnel", "Captain", "AI")
@@ -548,7 +557,7 @@
if(3)
R.fields["age"] = rand(5, 85)
if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
+ R.fields["criminal"] = pick(SEC_RECORD_STATUS_NONE, SEC_RECORD_STATUS_ARREST, SEC_RECORD_STATUS_SEARCH, SEC_RECORD_STATUS_MONITOR, SEC_RECORD_STATUS_DEMOTE, SEC_RECORD_STATUS_INCARCERATED, SEC_RECORD_STATUS_PAROLLED, SEC_RECORD_STATUS_RELEASED)
if(5)
R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
if(6)
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 9e07fb43b28..b7361db01a3 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -310,7 +310,7 @@
if(3)
R.fields["age"] = rand(5, 85)
if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
+ R.fields["criminal"] = pick(SEC_RECORD_STATUS_NONE, SEC_RECORD_STATUS_ARREST, SEC_RECORD_STATUS_INCARCERATED, SEC_RECORD_STATUS_PAROLLED, SEC_RECORD_STATUS_RELEASED)
if(5)
R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
if(6)
diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm
index f509ee42d34..2ba3b25b6f6 100644
--- a/code/game/machinery/computer/specops_shuttle.dm
+++ b/code/game/machinery/computer/specops_shuttle.dm
@@ -93,7 +93,7 @@ GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0)
GLOB.specops_shuttle_at_station = 0
- for(var/obj/machinery/computer/specops_shuttle/S in world)
+ for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
qdel(announcer)
@@ -160,10 +160,12 @@ GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0)
sleep(10)
var/spawn_marauder[] = new()
- for(var/obj/effect/landmark/L in world)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Marauder Entry")
spawn_marauder.Add(L.loc)
- for(var/obj/effect/landmark/L in world)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Marauder Exit")
var/obj/effect/portal/P = new(L.loc, pick(spawn_marauder))
//P.invisibility = 101//So it is not seen by anyone.
@@ -233,7 +235,7 @@ GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0)
var/mob/M = locate(/mob) in T
to_chat(M, "You have arrived to [station_name()]. Commence operation!")
- for(var/obj/machinery/computer/specops_shuttle/S in world)
+ for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
qdel(announcer)
@@ -241,7 +243,7 @@ GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0)
/proc/specops_can_move()
if(GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom)
return 0
- for(var/obj/machinery/computer/specops_shuttle/S in world)
+ for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
if(world.timeofday <= S.specops_shuttle_timereset)
return 0
return 1
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index fb630d7a251..607918442ea 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -20,7 +20,7 @@
/obj/machinery/computer/station_alert/New()
..()
alarm_monitor = new monitor_type(src)
- alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon)
+ alarm_monitor.register(src, /obj/machinery/computer/station_alert/.proc/update_icon)
/obj/machinery/computer/station_alert/Destroy()
alarm_monitor.unregister(src)
diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm
index 0a65b6be408..7ec7bd7a026 100644
--- a/code/game/machinery/computer/syndicate_specops_shuttle.dm
+++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm
@@ -23,7 +23,7 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0)
/proc/syndicate_elite_process()
var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work.
- var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located?
+ //var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located?
var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
@@ -63,7 +63,6 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0)
to_chat(usr, "The Syndicate Elite shuttle is unable to leave.")
return
- sleep(600)
/*
//Begin Marauder launchpad.
spawn(0)//So it parallel processes it.
@@ -129,11 +128,12 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0)
if("ASSAULT3")
spawn(0)
M.close()
- */
elite_squad.readyreset()//Reset firealarm after the team launched.
+ */
//End Marauder launchpad.
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Syndicate Breach Area")
explosion(L.loc,4,6,8,10,0)
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index efee10767ba..ee29504fe99 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -218,7 +218,7 @@
//Machine Frame Circuit Boards
/*Common Parts: Parts List: Ignitor, Timer, Infra-red laser, Infra-red sensor, t_scanner, Capacitor, Valve, sensor unit,
-micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells.
+micro-manipulator, glass sheets, beaker, Microlaser, matter bin, power cells.
Note: Once everything is added to the public areas, will add MAT_METAL and MAT_GLASS to circuit boards since autolathe won't be able
to destroy them and players will be able to make replacements.
*/
@@ -226,7 +226,6 @@ to destroy them and players will be able to make replacements.
name = "circuit board (Booze-O-Mat Vendor)"
board_type = "machine"
origin_tech = "programming=1"
- frame_desc = "Requires 1 Resupply Canister."
build_path = /obj/machinery/vending/boozeomat
req_components = list(/obj/item/vending_refill/boozeomat = 1)
@@ -282,7 +281,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/power/smes
board_type = "machine"
origin_tech = "programming=3;powerstorage=3;engineering=3"
- frame_desc = "Requires 5 pieces of cable, 5 Power Cells and 1 Capacitor."
req_components = list(
/obj/item/stack/cable_coil = 5,
/obj/item/stock_parts/cell = 5,
@@ -321,7 +319,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/atmospherics/unary/cold_sink/freezer
board_type = "machine"
origin_tech = "programming=3;plasmatech=3"
- frame_desc = "Requires 2 Matter Bins, 2 Micro Lasers, 1 piece of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/micro_laser = 2,
@@ -346,7 +343,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/recharger
board_type = "machine"
origin_tech = "powerstorage=3;materials=2"
- frame_desc = "Requires 1 Capacitor"
req_components = list(/obj/item/stock_parts/capacitor = 1)
/obj/item/circuitboard/snow_machine
@@ -354,7 +350,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/snow_machine
board_type = "machine"
origin_tech = "programming=2;materials=2"
- frame_desc = "Requires 1 Matter Bin and 1 Micro Laser."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/micro_laser = 1)
@@ -364,7 +359,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/biogenerator
board_type = "machine"
origin_tech = "programming=2;biotech=3;materials=3"
- frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -376,7 +370,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/plantgenes
board_type = "machine"
origin_tech = "programming=3;biotech=3"
- frame_desc = "Requires 1 Manipulator, 1 Micro Laser, 1 Console Screen, and 1 Scanning Module."
req_components = list(
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/micro_laser = 1,
@@ -390,7 +383,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/seed_extractor
board_type = "machine"
origin_tech = "programming=1"
- frame_desc = "Requires 1 Matter Bin and 1 Manipulator."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/manipulator = 1)
@@ -400,7 +392,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/hydroponics/constructable
board_type = "machine"
origin_tech = "programming=1;biotech=2"
- frame_desc = "Requires 2 Matter Bins, 1 Manipulator, and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/manipulator = 1,
@@ -411,7 +402,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/kitchen_machine/microwave
board_type = "machine"
origin_tech = "programming=2;magnets=2"
- frame_desc = "Requires 1 Micro Laser, 2 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stack/cable_coil = 2,
@@ -422,7 +412,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/kitchen_machine/oven
board_type = "machine"
origin_tech = "programming=2;magnets=2"
- frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/micro_laser = 2,
/obj/item/stack/cable_coil = 5,
@@ -433,7 +422,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/kitchen_machine/grill
board_type = "machine"
origin_tech = "programming=2;magnets=2"
- frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/micro_laser = 2,
/obj/item/stack/cable_coil = 5,
@@ -444,7 +432,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/kitchen_machine/candy_maker
board_type = "machine"
origin_tech = "programming=2;magnets=2"
- frame_desc = "Requires 1 Manipulator, 5 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/manipulator = 1,
/obj/item/stack/cable_coil = 5,
@@ -455,7 +442,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/cooker/deepfryer
board_type = "machine"
origin_tech = "programming=1"
- frame_desc = "Requires 2 Micro Lasers and 5 pieces of cable."
req_components = list(
/obj/item/stock_parts/micro_laser = 2,
/obj/item/stack/cable_coil = 5)
@@ -568,7 +554,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/chem_dispenser
board_type = "machine"
origin_tech = "materials=4;programming=4;plasmatech=4;biotech=3"
- frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Console Screen, and 1 Power Cell."
req_components = list( /obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/capacitor = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -609,7 +594,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/chem_heater
board_type = "machine"
origin_tech = "programming=2;engineering=2;biotech=2"
- frame_desc = "Requires 1 Micro Laser and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stack/sheet/glass = 1)
@@ -619,7 +603,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/reagentgrinder/empty
board_type = "machine"
origin_tech = "materials=2;engineering=2;biotech=2"
- frame_desc = "Requires 2 Manipulators and 1 Matter Bin."
req_components = list(
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/matter_bin = 1)
@@ -640,7 +623,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/r_n_d/destructive_analyzer
board_type = "machine"
origin_tech = "magnets=2;engineering=2;programming=2"
- frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro-Laser."
req_components = list(
/obj/item/stock_parts/scanning_module = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -651,7 +633,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/autolathe
board_type = "machine"
origin_tech = "engineering=2;programming=2"
- frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 3,
/obj/item/stock_parts/manipulator = 1,
@@ -662,7 +643,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/r_n_d/protolathe
board_type = "machine"
origin_tech = "engineering=2;programming=2"
- frame_desc = "Requires 2 Matter Bins, 2 Manipulators, and 2 Beakers."
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/manipulator = 2,
@@ -681,7 +661,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/r_n_d/circuit_imprinter
board_type = "machine"
origin_tech = "engineering=2;programming=2"
- frame_desc = "Requires 1 Matter Bin, 1 Manipulator, and 2 Beakers."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -692,7 +671,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/power/port_gen/pacman
board_type = "machine"
origin_tech = "programming=2;powerstorage=3;plasmatech=3;engineering=3"
- frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, 2 Pieces of Cable, and 1 Capacitor."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/micro_laser = 1,
@@ -714,7 +692,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/r_n_d/server
board_type = "machine"
origin_tech = "programming=3"
- frame_desc = "Requires 2 pieces of cable, and 1 Scanning Module."
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/stock_parts/scanning_module = 1)
@@ -724,7 +701,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/mecha_part_fabricator
board_type = "machine"
origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro-Laser and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/manipulator = 1,
@@ -736,7 +712,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/mecha_part_fabricator/spacepod
board_type = "machine"
origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Micro-Lasers, and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/manipulator = 1,
@@ -749,7 +724,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/clonepod
board_type = "machine"
origin_tech = "programming=2;biotech=2"
- frame_desc = "Requires 2 Manipulator, 2 Scanning Module, 2 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/stock_parts/scanning_module = 2,
@@ -761,7 +735,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/dna_scannernew
board_type = "machine"
origin_tech = "programming=2;biotech=2"
- frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro-Laser, 2 pieces of cable and 1 Console Screen."
req_components = list(
/obj/item/stock_parts/scanning_module = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -774,7 +747,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/mech_bay_recharge_port
board_type = "machine"
origin_tech = "programming=3;powerstorage=3;engineering=3"
- frame_desc = "Requires 1 piece of cable and 5 Capacitors."
req_components = list(
/obj/item/stack/cable_coil = 1,
/obj/item/stock_parts/capacitor = 5)
@@ -784,7 +756,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/teleport/hub
board_type = "machine"
origin_tech = "programming=3;engineering=4;bluespace=4;materials=4"
- frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin."
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 3,
/obj/item/stock_parts/matter_bin = 1)
@@ -794,7 +765,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/teleport/station
board_type = "machine"
origin_tech = "programming=4;engineering=4;bluespace=4;plasmatech=3"
- frame_desc = "Requires 2 Bluespace Crystals, 2 Capacitors and 1 Console Screen."
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 2,
/obj/item/stock_parts/capacitor = 2,
@@ -805,7 +775,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/teleport/perma
board_type = "machine"
origin_tech = "programming=3;engineering=4;bluespace=4;materials=4"
- frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin."
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 3,
/obj/item/stock_parts/matter_bin = 1)
@@ -825,7 +794,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/telepad
board_type = "machine"
origin_tech = "programming=4;engineering=3;plasmatech=4;bluespace=4"
- frame_desc = "Requires 2 Bluespace Crystals, 1 Capacitor, 1 piece of cable and 1 Console Screen."
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 2,
/obj/item/stock_parts/capacitor = 1,
@@ -837,7 +805,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/quantumpad
board_type = "machine"
origin_tech = "programming=3;engineering=3;plasmatech=3;bluespace=4"
- frame_desc = "Requires 1 Bluespace Crystal, 1 Capacitor, 1 piece of cable and 1 Manipulator."
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 1,
/obj/item/stock_parts/capacitor = 1,
@@ -849,7 +816,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/sleeper
board_type = "machine"
origin_tech = "programming=3;biotech=2;engineering=3"
- frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Console Screens."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/manipulator = 1,
@@ -870,7 +836,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/bodyscanner
board_type = "machine"
origin_tech = "programming=3;biotech=2;engineering=3"
- frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Console Screens."
req_components = list(
/obj/item/stock_parts/scanning_module = 1,
/obj/item/stack/cable_coil = 2,
@@ -881,7 +846,6 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/atmospherics/unary/cryo_cell
board_type = "machine"
origin_tech = "programming=4;biotech=3;engineering=4;plasmatech=3"
- frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Console Screens."
req_components = list(
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stack/cable_coil = 1,
@@ -892,96 +856,26 @@ to destroy them and players will be able to make replacements.
build_path = /obj/machinery/recharge_station
board_type = "machine"
origin_tech = "powerstorage=3;engineering=3"
- frame_desc = "Requires 2 Capacitors, 1 Power Cell and 1 Manipulator."
req_components = list(
/obj/item/stock_parts/capacitor = 2,
/obj/item/stock_parts/cell = 1,
/obj/item/stock_parts/manipulator = 1)
// Telecomms circuit boards:
-/obj/item/circuitboard/telecomms/receiver
- name = "Circuit Board (Subspace Receiver)"
- build_path = /obj/machinery/telecomms/receiver
- board_type = "machine"
- origin_tech = "programming=2;engineering=2;bluespace=1"
- frame_desc = "Requires 1 Subspace Ansible, 1 Hyperwave Filter, 2 Manipulators, and 1 Micro-Laser."
- req_components = list(
- /obj/item/stock_parts/subspace/ansible = 1,
- /obj/item/stock_parts/subspace/filter = 1,
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stock_parts/micro_laser = 1)
-
-/obj/item/circuitboard/telecomms/hub
- name = "Circuit Board (Hub Mainframe)"
- build_path = /obj/machinery/telecomms/hub
- board_type = "machine"
- origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filter."
- req_components = list(
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/subspace/filter = 2)
-
-/obj/item/circuitboard/telecomms/relay
- name = "Circuit Board (Relay Mainframe)"
- build_path = /obj/machinery/telecomms/relay
+/obj/item/circuitboard/tcomms/relay
+ name = "Circuit Board (Telecommunications Relay)"
+ build_path = /obj/machinery/tcomms/relay
board_type = "machine"
origin_tech = "programming=2;engineering=2;bluespace=2"
- frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filters."
- req_components = list(
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/subspace/filter = 2)
+ req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2)
-/obj/item/circuitboard/telecomms/bus
- name = "Circuit Board (Bus Mainframe)"
- build_path = /obj/machinery/telecomms/bus
+/obj/item/circuitboard/tcomms/core
+ name = "Circuit Board (Telecommunications Core)"
+ build_path = /obj/machinery/tcomms/core
board_type = "machine"
origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter."
- req_components = list(
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stack/cable_coil = 1,
- /obj/item/stock_parts/subspace/filter = 1)
-
-/obj/item/circuitboard/telecomms/processor
- name = "Circuit Board (Processor Unit)"
- build_path = /obj/machinery/telecomms/processor
- board_type = "machine"
- origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 3 Manipulators, 1 Hyperwave Filter, 2 Treatment Disks, 1 Wavelength Analyzer, 2 Cable Coils and 1 Subspace Amplifier."
- req_components = list(
- /obj/item/stock_parts/manipulator = 3,
- /obj/item/stock_parts/subspace/filter = 1,
- /obj/item/stock_parts/subspace/treatment = 2,
- /obj/item/stock_parts/subspace/analyzer = 1,
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/subspace/amplifier = 1)
-
-/obj/item/circuitboard/telecomms/server
- name = "Circuit Board (Telecommunication Server)"
- build_path = /obj/machinery/telecomms/server
- board_type = "machine"
- origin_tech = "programming=2;engineering=2"
- frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter."
- req_components = list(
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stack/cable_coil = 1,
- /obj/item/stock_parts/subspace/filter = 1)
-
-/obj/item/circuitboard/telecomms/broadcaster
- name = "Circuit Board (Subspace Broadcaster)"
- build_path = /obj/machinery/telecomms/broadcaster
- board_type = "machine"
- origin_tech = "programming=2;engineering=2;bluespace=1"
- frame_desc = "Requires 2 Manipulators, 1 Cable Coil, 1 Hyperwave Filter, 1 Ansible Crystal and 2 High-Powered Micro-Lasers. "
- req_components = list(
- /obj/item/stock_parts/manipulator = 2,
- /obj/item/stack/cable_coil = 1,
- /obj/item/stock_parts/subspace/filter = 1,
- /obj/item/stock_parts/subspace/crystal = 1,
- /obj/item/stock_parts/micro_laser/high = 2)
-
+ req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2)
+// End telecomms circuit boards
/obj/item/circuitboard/ore_redemption
name = "circuit board (Ore Redemption)"
build_path = /obj/machinery/mineral/ore_redemption
@@ -1042,50 +936,3 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stack/cable_coil = 3,
/obj/item/stack/sheet/glass = 1)
-
-//Selectable mode board, like vending machine boards
-/obj/item/circuitboard/logic_gate
- name = "circuit board (Logic Connector)"
- build_path = /obj/machinery/logic_gate
- board_type = "machine"
- origin_tech = "programming=1" //This stuff is pretty much the absolute basis of programming, so it's mostly useless for research
- req_components = list(/obj/item/stack/cable_coil = 1)
-
- var/list/names_paths = list(
- "NOT Gate" = /obj/machinery/logic_gate/not,
- "OR Gate" = /obj/machinery/logic_gate/or,
- "AND Gate" = /obj/machinery/logic_gate/and,
- "NAND Gate" = /obj/machinery/logic_gate/nand,
- "NOR Gate" = /obj/machinery/logic_gate/nor,
- "XOR Gate" = /obj/machinery/logic_gate/xor,
- "XNOR Gate" = /obj/machinery/logic_gate/xnor,
- "STATUS Gate" = /obj/machinery/logic_gate/status,
- "CONVERT Gate" = /obj/machinery/logic_gate/convert
- )
-
-/obj/item/circuitboard/logic_gate/New()
- ..()
- if(build_path == /obj/machinery/logic_gate) //If we spawn the base type board (determined by the base type machine as the build path), become a random gate board
- var/new_path = names_paths[pick(names_paths)]
- set_type(new_path)
-
-/obj/item/circuitboard/logic_gate/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/screwdriver))
- set_type(null, user)
- return
- return ..()
-
-/obj/item/circuitboard/logic_gate/proc/set_type(typepath, mob/user)
- var/new_name = "Logic Base"
- if(!typepath)
- new_name = input("Circuit Setting", "What would you change the board setting to?") in names_paths
- typepath = names_paths[new_name]
- else
- for(var/name in names_paths)
- if(names_paths[name] == typepath)
- new_name = name
- break
- build_path = typepath
- name = "circuit board ([new_name])"
- if(user)
- to_chat(user, "You set the board to [new_name].")
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index a99384d364a..4213ff517bf 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -1,3 +1,6 @@
+#define AUTO_EJECT_DEAD (1<<0)
+#define AUTO_EJECT_HEALTHY (1<<1)
+
/obj/machinery/atmospherics/unary/cryo_cell
name = "cryo cell"
desc = "Lowers the body temperature so certain medications may take effect."
@@ -10,11 +13,12 @@
interact_offline = 1
max_integrity = 350
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 30, "acid" = 30)
- var/on = 0
+ var/on = FALSE
var/temperature_archived
var/mob/living/carbon/occupant = null
var/obj/item/reagent_containers/glass/beaker = null
- var/autoeject = 0
+ /// Holds two bitflags, AUTO_EJECT_DEAD and AUTO_EJECT_HEALTHY. Used to determine if the cryo cell will auto-eject dead and/or completely health patients.
+ var/auto_eject_prefs = NONE
var/next_trans = 0
var/current_heat_capacity = 50
@@ -139,18 +143,20 @@
/obj/machinery/atmospherics/unary/cryo_cell/process()
..()
- if(autoeject)
- if(occupant)
- if(!occupant.has_organic_damage() && !occupant.has_mutated_organs())
- on = 0
- go_out()
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ if(!occupant)
+ return
+
+ if((auto_eject_prefs & AUTO_EJECT_DEAD) && occupant.stat == DEAD)
+ auto_eject(AUTO_EJECT_DEAD)
+ return
+ if((auto_eject_prefs & AUTO_EJECT_HEALTHY) && !occupant.has_organic_damage() && !occupant.has_mutated_organs())
+ auto_eject(AUTO_EJECT_HEALTHY)
+ return
if(air_contents)
- if(occupant)
- process_occupant()
+ process_occupant()
- return 1
+ return TRUE
/obj/machinery/atmospherics/unary/cryo_cell/process_atmos()
..()
@@ -208,7 +214,7 @@
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 420)
+ ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 480)
// open the new ui window
ui.open()
// auto update every Master Controller tick
@@ -231,7 +237,7 @@
occupantData["toxLoss"] = occupant.getToxLoss()
occupantData["fireLoss"] = occupant.getFireLoss()
occupantData["bodyTemperature"] = occupant.bodytemperature
- data["occupant"] = occupantData;
+ data["occupant"] = occupantData
data["cellTemperature"] = round(air_contents.temperature)
data["cellTemperatureStatus"] = "good"
@@ -249,7 +255,8 @@
for(var/datum/reagent/R in beaker.reagents.reagent_list)
data["beakerVolume"] += R.volume
- data["autoeject"] = autoeject
+ data["auto_eject_healthy"] = (auto_eject_prefs & AUTO_EJECT_HEALTHY) ? TRUE : FALSE
+ data["auto_eject_dead"] = (auto_eject_prefs & AUTO_EJECT_DEAD) ? TRUE : FALSE
return data
/obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list)
@@ -260,18 +267,24 @@
return 0 // don't update UIs attached to this object
if(href_list["switchOn"])
- on = 1
+ on = TRUE
update_icon()
if(href_list["switchOff"])
- on = 0
+ on = FALSE
update_icon()
- if(href_list["autoejectOn"])
- autoeject = 1
+ if(href_list["auto_eject_healthy_on"])
+ auto_eject_prefs |= AUTO_EJECT_HEALTHY
- if(href_list["autoejectOff"])
- autoeject = 0
+ if(href_list["auto_eject_healthy_off"])
+ auto_eject_prefs &= ~AUTO_EJECT_HEALTHY
+
+ if(href_list["auto_eject_dead_on"])
+ auto_eject_prefs |= AUTO_EJECT_DEAD
+
+ if(href_list["auto_eject_dead_off"])
+ auto_eject_prefs &= ~AUTO_EJECT_DEAD
if(href_list["ejectBeaker"])
if(beaker)
@@ -430,6 +443,16 @@
for(var/atom/movable/A in contents - component_parts - list(beaker))
A.forceMove(get_step(loc, SOUTH))
+/// Called when either the occupant is dead and the AUTO_EJECT_DEAD flag is present, OR the occupant is alive, has no external damage, and the AUTO_EJECT_HEALTHY flag is present.
+/obj/machinery/atmospherics/unary/cryo_cell/proc/auto_eject(eject_flag)
+ on = FALSE
+ go_out()
+ switch(eject_flag)
+ if(AUTO_EJECT_HEALTHY)
+ playsound(loc, 'sound/machines/ding.ogg', 50, 1)
+ if(AUTO_EJECT_DEAD)
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 40)
+
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
if(!istype(M))
to_chat(usr, "The cryo cell cannot handle such a lifeform!")
@@ -493,7 +516,7 @@
if(stat & (NOPOWER|BROKEN))
return
- if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other
+ if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
return
put_mob(usr)
@@ -510,8 +533,17 @@
/datum/data/function/proc/display()
return
-/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
+/obj/machinery/atmospherics/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1)
-/obj/machinery/atmospherics/components/unary/cryo_cell/update_remote_sight(mob/living/user)
+/obj/machinery/atmospherics/unary/cryo_cell/update_remote_sight(mob/living/user)
return //we don't see the pipe network while inside cryo.
+
+/obj/machinery/atmospherics/unary/cryo_cell/can_crawl_through()
+ return // can't ventcrawl in or out of cryo.
+
+/obj/machinery/atmospherics/unary/cryo_cell/can_see_pipes()
+ return FALSE // you can't see the pipe network when inside a cryo cell.
+
+#undef AUTO_EJECT_HEALTHY
+#undef AUTO_EJECT_DEAD
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 37d59977f3e..2e0c4c54375 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -275,6 +275,12 @@
return control_computer != null
+// So the user can use movement keys to get out of the cryopod
+/obj/machinery/cryopod/relaymove(mob/user)
+ if(user.incapacitated())
+ return FALSE
+ go_out()
+
/obj/machinery/cryopod/proc/check_occupant_allowed(mob/M)
var/correct_type = 0
for(var/type in allow_occupant_types)
@@ -296,6 +302,7 @@
// Eject dead people
if(occupant.stat == DEAD)
go_out()
+ return
// Allow a gap between entering the pod and actually despawning.
if(world.time - time_entered < time_till_despawn)
@@ -438,7 +445,7 @@
control_computer.frozen_crew += "[occupant.real_name]"
var/ailist[] = list()
- for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
ailist += A
if(ailist.len)
var/mob/living/silicon/ai/announcer = pick(ailist)
@@ -665,6 +672,9 @@
to_chat(usr, "[usr] will not fit into [src] because [usr.p_they()] [usr.p_have()] a slime latched onto [usr.p_their()] head.")
return
+ if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
+ return
+
visible_message("[usr] starts climbing into [src].")
if(do_after(usr, 20, target = usr))
diff --git a/code/game/machinery/defib_mount.dm b/code/game/machinery/defib_mount.dm
index d669b340436..79d02155832 100644
--- a/code/game/machinery/defib_mount.dm
+++ b/code/game/machinery/defib_mount.dm
@@ -15,6 +15,9 @@
var/obj/item/defibrillator/defib //this mount's defibrillator
var/clamps_locked = FALSE //if true, and a defib is loaded, it can't be removed without unlocking the clamps
+/obj/machinery/defibrillator_mount/attack_ai()
+ return
+
/obj/machinery/defibrillator_mount/get_cell()
if(defib)
return defib.get_cell()
@@ -26,11 +29,10 @@
loc = location
if(direction)
- dir = direction
+ setDir(direction)
if(building)
- pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30)
- pixel_y = (dir & 3)? (dir == 1 ? -30 : 30) : 0
+ set_pixel_offsets_from_dir(30, -30, 30, -30)
/obj/machinery/defibrillator_mount/loaded/New() //loaded subtype for mapping use
..()
@@ -154,6 +156,6 @@
w_class = WEIGHT_CLASS_BULKY
/obj/item/mounted/frame/defib_mount/do_build(turf/on_wall, mob/user)
- new /obj/machinery/defibrillator_mount(get_turf(src), get_dir(on_wall, user), 1)
+ new /obj/machinery/defibrillator_mount(get_turf(src), get_dir(user, on_wall), 1)
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
qdel(src)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 1d97056912f..ffb56109e9e 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -30,6 +30,8 @@
new stacktype(get_turf(src), drop_amount)
/obj/structure/barricade/welder_act(mob/user, obj/item/I)
+ if(bar_material != METAL)
+ return
if(obj_integrity >= max_integrity)
to_chat(user, "[src] does not need repairs.")
return
@@ -40,7 +42,7 @@
WELDER_ATTEMPT_REPAIR_MESSAGE
if(I.use_tool(src, user, 40, volume = I.tool_volume))
WELDER_REPAIR_SUCCESS_MESSAGE
- obj_integrity = Clamp(obj_integrity + 20, 0, max_integrity)
+ obj_integrity = clamp(obj_integrity + 20, 0, max_integrity)
update_icon()
return TRUE
@@ -71,6 +73,7 @@
bar_material = WOOD
stacktype = /obj/item/stack/sheet/wood
+
/obj/structure/barricade/wooden/attackby(obj/item/I, mob/user)
if(istype(I,/obj/item/stack/sheet/wood))
var/obj/item/stack/sheet/wood/W = I
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 692024899a2..42ff08ff00f 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -80,6 +80,7 @@ GLOBAL_LIST_EMPTY(airlock_overlays)
var/note_overlay_file = 'icons/obj/doors/airlocks/station/overlays.dmi' //Used for papers and photos pinned to the airlock
var/normal_integrity = AIRLOCK_INTEGRITY_N
var/prying_so_hard = FALSE
+ var/paintable = TRUE // If the airlock type can be painted with an airlock painter
var/image/old_frame_overlay //keep those in order to prevent unnecessary updating
var/image/old_filling_overlay
@@ -192,10 +193,10 @@ About the new airlock wires panel:
return wires.IsIndexCut(wireIndex)
/obj/machinery/door/airlock/proc/canAIControl()
- return ((aiControlDisabled!=1) && (!isAllPowerLoss()));
+ return ((aiControlDisabled!=1) && (!isAllPowerLoss()))
/obj/machinery/door/airlock/proc/canAIHack()
- return ((aiControlDisabled==1) && (!hackProof) && (!isAllPowerLoss()));
+ return ((aiControlDisabled==1) && (!hackProof) && (!isAllPowerLoss()))
/obj/machinery/door/airlock/proc/arePowerSystemsOn()
if(stat & (NOPOWER|BROKEN))
@@ -219,21 +220,21 @@ About the new airlock wires panel:
return isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)
/obj/machinery/door/airlock/proc/loseMainPower()
- main_power_lost_until = mainPowerCablesCut() ? -1 : world.time + SecondsToTicks(60)
+ main_power_lost_until = mainPowerCablesCut() ? -1 : world.time + 60 SECONDS
if(main_power_lost_until > 0)
- main_power_timer = addtimer(CALLBACK(src, .proc/regainMainPower), SecondsToTicks(60), TIMER_UNIQUE | TIMER_STOPPABLE)
+ main_power_timer = addtimer(CALLBACK(src, .proc/regainMainPower), 60 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
// If backup power is permanently disabled then activate in 10 seconds if possible, otherwise it's already enabled or a timer is already running
if(backup_power_lost_until == -1 && !backupPowerCablesCut())
- backup_power_lost_until = world.time + SecondsToTicks(10)
- backup_power_timer = addtimer(CALLBACK(src, .proc/regainBackupPower), SecondsToTicks(10), TIMER_UNIQUE | TIMER_STOPPABLE)
+ backup_power_lost_until = world.time + 10 SECONDS
+ backup_power_timer = addtimer(CALLBACK(src, .proc/regainBackupPower), 10 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
// Disable electricity if required
if(electrified_until && isAllPowerLoss())
electrify(0)
/obj/machinery/door/airlock/proc/loseBackupPower()
- backup_power_lost_until = backupPowerCablesCut() ? -1 : world.time + SecondsToTicks(60)
+ backup_power_lost_until = backupPowerCablesCut() ? -1 : world.time + 60 SECONDS
if(backup_power_lost_until > 0)
- backup_power_timer = addtimer(CALLBACK(src, .proc/regainBackupPower), SecondsToTicks(60), TIMER_UNIQUE | TIMER_STOPPABLE)
+ backup_power_timer = addtimer(CALLBACK(src, .proc/regainBackupPower), 60 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
// Disable electricity if required
if(electrified_until && isAllPowerLoss())
@@ -276,21 +277,21 @@ About the new airlock wires panel:
if(usr)
shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])")
usr.create_attack_log("Electrified the [name] at [x] [y] [z]")
- add_attack_logs(usr, src, "Electrified")
+ add_attack_logs(usr, src, "Electrified", ATKLOG_ALL)
else
shockedby += text("\[[time_stamp()]\] - EMP)")
message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]."
- electrified_until = duration == -1 ? -1 : world.time + SecondsToTicks(duration)
+ electrified_until = duration == -1 ? -1 : world.time + duration SECONDS
if(duration != -1)
- electrified_timer = addtimer(CALLBACK(src, .proc/electrify, 0), SecondsToTicks(duration), TIMER_UNIQUE | TIMER_STOPPABLE)
+ electrified_timer = addtimer(CALLBACK(src, .proc/electrify, 0), duration SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
if(feedback && message)
to_chat(usr, message)
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
-/obj/machinery/door/airlock/shock(mob/user, prb)
- if(!arePowerSystemsOn())
+/obj/machinery/door/airlock/shock(mob/living/user, prb)
+ if(!istype(user) || !arePowerSystemsOn())
return FALSE
if(shockCooldown > world.time)
return FALSE //Already shocked someone recently?
@@ -502,6 +503,36 @@ About the new airlock wires panel:
sleep(6)
update_icon(AIRLOCK_CLOSED)
+
+/// Called when a player uses an airlock painter on this airlock
+/obj/machinery/door/airlock/proc/change_paintjob(obj/item/airlock_painter/painter, mob/user)
+ if((!in_range(src, user) && loc != user)) // user should be adjacent to the airlock.
+ return
+
+ if(!painter.paint_setting)
+ to_chat(user, "You need to select a paintjob first.")
+ return
+
+ if(!paintable)
+ to_chat(user, "This type of airlock cannot be painted.")
+ return
+
+ var/obj/machinery/door/airlock/airlock = painter.available_paint_jobs["[painter.paint_setting]"] // get the airlock type path associated with the airlock name the user just chose
+ var/obj/structure/door_assembly/assembly = initial(airlock.assemblytype)
+
+ if(airlock_material == "glass" && initial(assembly.noglass)) // prevents painting glass airlocks with a paint job that doesn't have a glass version, such as the freezer
+ to_chat(user, "This paint job can only be applied to non-glass airlocks.")
+ return
+
+ if(do_after(user, 20, target = src))
+ // applies the user-chosen airlock's icon, overlays and assemblytype to the src airlock
+ painter.paint(user)
+ icon = initial(airlock.icon)
+ overlays_file = initial(airlock.overlays_file)
+ assemblytype = initial(airlock.assemblytype)
+ update_icon()
+
+
/obj/machinery/door/airlock/examine(mob/user)
. = ..()
if(emagged)
@@ -764,7 +795,7 @@ About the new airlock wires panel:
else if(activate) //electrify door for 30 seconds
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.create_attack_log("Electrified the [name] at [x] [y] [z]")
- add_attack_logs(usr, src, "Electrified")
+ add_attack_logs(usr, src, "Electrified", ATKLOG_ALL)
to_chat(usr, "The door is now electrified for thirty seconds.")
electrify(30)
if("electrify_permanently")
@@ -776,7 +807,7 @@ About the new airlock wires panel:
else if(activate)
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.create_attack_log("Electrified the [name] at [x] [y] [z]")
- add_attack_logs(usr, src, "Electrified")
+ add_attack_logs(usr, src, "Electrified", ATKLOG_ALL)
to_chat(usr, "The door is now electrified.")
electrify(-1)
if("open")
@@ -864,7 +895,7 @@ About the new airlock wires panel:
update_icon()
return
- else if(istype(C, /obj/item/assembly/signaler))
+ if(istype(C, /obj/item/assembly/signaler))
return interact_with_panel(user)
else if(istype(C, /obj/item/pai_cable)) // -- TLE
var/obj/item/pai_cable/cable = C
@@ -876,10 +907,14 @@ About the new airlock wires panel:
if(!user.unEquip(C))
to_chat(user, "For some reason, you can't attach [C]!")
return
+ C.add_fingerprint(user)
+ user.create_log(MISC_LOG, "put [C] on", src)
C.forceMove(src)
user.visible_message("[user] pins [C] to [src].", "You pin [C] to [src].")
note = C
update_icon()
+ else if(istype(C, /obj/item/airlock_painter))
+ change_paintjob(C, user)
else
return ..()
@@ -933,7 +968,7 @@ About the new airlock wires panel:
if(!panel_open || user.a_intent == INTENT_HARM)
return
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(security_level == AIRLOCK_SECURITY_PLASTEEL)
if(arePowerSystemsOn() && shock(user, 60)) // Protective grille of wiring is electrified
@@ -949,7 +984,7 @@ About the new airlock wires panel:
if(note)
remove_airlock_note(user, TRUE)
else
- return interact_with_panel(user)
+ interact_with_panel(user)
/obj/machinery/door/airlock/multitool_act(mob/user, obj/item/I)
if(!headbutt_shock_check(user))
@@ -965,63 +1000,58 @@ About the new airlock wires panel:
. = TRUE
if(!I.tool_use_check(user, 0))
return
- switch(security_level)
- if(AIRLOCK_SECURITY_METAL)
- to_chat(user, "You begin cutting the panel's shielding...")
- if(!I.use_tool(src, user, 40, volume = I.tool_volume))
- return
- if(!panel_open)
- return
- visible_message("[user] cuts through \the [src]'s shielding.",
- "You cut through \the [src]'s shielding.",
- "You hear welding.")
- security_level = AIRLOCK_SECURITY_NONE
- spawn_atom_to_turf(/obj/item/stack/sheet/metal, user.loc, 2)
- if(AIRLOCK_SECURITY_PLASTEEL_O)
- to_chat(user, "You begin cutting the outer layer of shielding...")
- if(!I.use_tool(src, user, 40, volume = I.tool_volume))
- return
- if(!panel_open)
- return
- visible_message("[user] cuts through \the [src]'s shielding.",
- "You cut through \the [src]'s shielding.",
- "You hear welding.")
- security_level = AIRLOCK_SECURITY_PLASTEEL_O_S
- if(AIRLOCK_SECURITY_PLASTEEL_I)
- to_chat(user, "You begin cutting the inner layer of shielding...")
- if(!I.use_tool(src, user, 40, volume = I.tool_volume))
- return
- if(!panel_open)
- return
- user.visible_message("[user] cuts through \the [src]'s shielding.",
- "You cut through \the [src]'s shielding.",
- "You hear welding.")
- security_level = AIRLOCK_SECURITY_PLASTEEL_I_S
- else
- if(user.a_intent != INTENT_HELP)
- user.visible_message("[user] is [welded ? "unwelding":"welding"] the airlock.", \
- "You begin [welded ? "unwelding":"welding"] the airlock...", \
+ if(panel_open) // panel should be open before we try to slice out any shielding.
+ switch(security_level)
+ if(AIRLOCK_SECURITY_METAL)
+ to_chat(user, "You begin cutting the panel's shielding...")
+ if(!I.use_tool(src, user, 40, volume = I.tool_volume))
+ return
+ visible_message("[user] cuts through \the [src]'s shielding.",
+ "You cut through \the [src]'s shielding.",
"You hear welding.")
+ security_level = AIRLOCK_SECURITY_NONE
+ spawn_atom_to_turf(/obj/item/stack/sheet/metal, user.loc, 2)
+ if(AIRLOCK_SECURITY_PLASTEEL_O)
+ to_chat(user, "You begin cutting the outer layer of shielding...")
+ if(!I.use_tool(src, user, 40, volume = I.tool_volume))
+ return
+ visible_message("[user] cuts through \the [src]'s shielding.",
+ "You cut through \the [src]'s shielding.",
+ "You hear welding.")
+ security_level = AIRLOCK_SECURITY_PLASTEEL_O_S
+ if(AIRLOCK_SECURITY_PLASTEEL_I)
+ to_chat(user, "You begin cutting the inner layer of shielding...")
+ if(!I.use_tool(src, user, 40, volume = I.tool_volume))
+ return
+ user.visible_message("[user] cuts through \the [src]'s shielding.",
+ "You cut through \the [src]'s shielding.",
+ "You hear welding.")
+ security_level = AIRLOCK_SECURITY_PLASTEEL_I_S
+ else
+ if(user.a_intent != INTENT_HELP)
+ user.visible_message("[user] is [welded ? "unwelding":"welding"] the airlock.", \
+ "You begin [welded ? "unwelding":"welding"] the airlock...", \
+ "You hear welding.")
- if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
- if(!density && !welded)
- return
- welded = !welded
- user.visible_message("[user.name] has [welded? "welded shut":"unwelded"] [src].", \
- "You [welded ? "weld the airlock shut":"unweld the airlock"].")
- update_icon()
- else if(obj_integrity < max_integrity)
- user.visible_message("[user] is welding the airlock.", \
- "You begin repairing the airlock...", \
- "You hear welding.")
- if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
- obj_integrity = max_integrity
- stat &= ~BROKEN
- user.visible_message("[user.name] has repaired [src].", \
- "You finish repairing the airlock.")
+ if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
+ if(!density && !welded)
+ return
+ welded = !welded
+ user.visible_message("[user.name] has [welded? "welded shut":"unwelded"] [src].", \
+ "You [welded ? "weld the airlock shut":"unweld the airlock"].")
update_icon()
- else
- to_chat(user, "The airlock doesn't need repairing.")
+ else if(obj_integrity < max_integrity)
+ user.visible_message("[user] is welding the airlock.", \
+ "You begin repairing the airlock...", \
+ "You hear welding.")
+ if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
+ obj_integrity = max_integrity
+ stat &= ~BROKEN
+ user.visible_message("[user.name] has repaired [src].", \
+ "You finish repairing the airlock.")
+ update_icon()
+ else
+ to_chat(user, "The airlock doesn't need repairing.")
update_icon()
/obj/machinery/door/airlock/proc/weld_checks(obj/item/I, mob/user)
@@ -1217,7 +1247,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/emp_act(severity)
..()
if(prob(40/severity))
- var/duration = world.time + SecondsToTicks(30 / severity)
+ var/duration = world.time + (30 / severity) SECONDS
if(duration > electrified_until)
electrify(duration)
@@ -1347,10 +1377,13 @@ About the new airlock wires panel:
if (ishuman(user) && user.a_intent == INTENT_GRAB)//grab that note
user.visible_message("[user] removes [note] from [src].", "You remove [note] from [src].")
playsound(src, 'sound/items/poster_ripped.ogg', 50, 1)
- else return FALSE
+ else
+ return FALSE
else
user.visible_message("[user] cuts down [note] from [src].", "You remove [note] from [src].")
playsound(src, 'sound/items/wirecutter.ogg', 50, 1)
+ note.add_fingerprint(user)
+ user.create_log(MISC_LOG, "removed [note] from", src)
user.put_in_hands(note)
note = null
update_icon()
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index fccb77c5e2a..dd9581a5af3 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -115,6 +115,7 @@
name = "gold airlock"
icon = 'icons/obj/doors/airlocks/station/gold.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_gold
+ paintable = FALSE
/obj/machinery/door/airlock/gold/glass
opacity = 0
@@ -124,6 +125,7 @@
name = "silver airlock"
icon = 'icons/obj/doors/airlocks/station/silver.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_silver
+ paintable = FALSE
/obj/machinery/door/airlock/silver/glass
opacity = 0
@@ -135,6 +137,7 @@
assemblytype = /obj/structure/door_assembly/door_assembly_diamond
normal_integrity = 1000
explosion_block = 2
+ paintable = FALSE
/obj/machinery/door/airlock/diamond/glass
normal_integrity = 950
@@ -146,6 +149,7 @@
desc = "And they said I was crazy."
icon = 'icons/obj/doors/airlocks/station/uranium.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_uranium
+ paintable = FALSE
var/event_step = 20
/obj/machinery/door/airlock/uranium/New()
@@ -169,6 +173,7 @@
desc = "No way this can end badly."
icon = 'icons/obj/doors/airlocks/station/plasma.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_plasma
+ paintable = FALSE
/obj/machinery/door/airlock/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
@@ -214,6 +219,7 @@
assemblytype = /obj/structure/door_assembly/door_assembly_bananium
doorOpen = 'sound/items/bikehorn.ogg'
doorClose = 'sound/items/bikehorn.ogg'
+ paintable = FALSE
/obj/machinery/door/airlock/bananium/glass
opacity = 0
@@ -227,11 +233,13 @@
doorDeni = null
boltUp = null
boltDown = null
+ paintable = FALSE
/obj/machinery/door/airlock/sandstone
name = "sandstone airlock"
icon = 'icons/obj/doors/airlocks/station/sandstone.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_sandstone
+ paintable = FALSE
/obj/machinery/door/airlock/sandstone/glass
opacity = 0
@@ -241,6 +249,7 @@
name = "wooden airlock"
icon = 'icons/obj/doors/airlocks/station/wood.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_wood
+ paintable = FALSE
/obj/machinery/door/airlock/wood/glass
opacity = 0
@@ -252,6 +261,7 @@
icon = 'icons/obj/doors/airlocks/shuttle/shuttle.dmi'
overlays_file = 'icons/obj/doors/airlocks/shuttle/overlays.dmi'
normal_integrity = 400
+ paintable = FALSE
/obj/machinery/door/airlock/titanium/glass
normal_integrity = 350
@@ -317,6 +327,7 @@
explosion_block = 2
normal_integrity = 400 // reverse engieneerd: 400 * 1.5 (sec lvl 6) = 600 = original
security_level = 6
+ paintable = FALSE
//////////////////////////////////
/*
@@ -329,6 +340,7 @@
overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_hatch
+ paintable = FALSE
/obj/machinery/door/airlock/hatch/syndicate
name = "syndicate hatch"
@@ -400,6 +412,7 @@
overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_mhatch
+ paintable = FALSE
//////////////////////////////////
/*
@@ -415,6 +428,7 @@
normal_integrity = 500
security_level = 1
damage_deflection = 30
+ paintable = FALSE
/obj/machinery/door/airlock/highsecurity/red
name = "secure armory airlock"
@@ -457,6 +471,7 @@
icon = 'icons/obj/doors/airlocks/shuttle/shuttle.dmi'
overlays_file = 'icons/obj/doors/airlocks/shuttle/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_shuttle
+ paintable = FALSE
/obj/machinery/door/airlock/shuttle/glass
opacity = 0
@@ -475,6 +490,7 @@
aiControlDisabled = 1
normal_integrity = 700
security_level = 1
+ paintable = FALSE
//////////////////////////////////
/*
@@ -489,6 +505,7 @@
damage_deflection = 10
hackProof = TRUE
aiControlDisabled = TRUE
+ paintable = FALSE
var/openingoverlaytype = /obj/effect/temp_visual/cult/door
var/friendly = FALSE
@@ -575,6 +592,7 @@
overlays_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
assemblytype = /obj/structure/door_assembly/multi_tile
+ paintable = FALSE
/obj/machinery/door/airlock/multi_tile/narsie_act()
return
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index 29549a05630..9970974e4ff 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -2,6 +2,7 @@
#define FONT_SIZE "5pt"
#define FONT_COLOR "#09f"
#define FONT_STYLE "Small Fonts"
+#define CELL_NONE "None"
///////////////////////////////////////////////////////////////////////////////////////////////
// Brig Door control displays.
@@ -31,10 +32,13 @@
maptext_height = 26
maptext_width = 32
maptext_y = -1
- var/occupant = "None"
- var/crimes = "None"
+ var/occupant = CELL_NONE
+ var/crimes = CELL_NONE
var/time = 0
- var/officer = "None"
+ var/officer = CELL_NONE
+ var/prisoner_name = ""
+ var/prisoner_charge = ""
+ var/prisoner_time = ""
/obj/machinery/door_timer/New()
GLOB.celltimers_list += src
@@ -45,33 +49,29 @@
return ..()
/obj/machinery/door_timer/proc/print_report()
- var/logname = input(usr, "Name of the guilty?","[id] log name")
- var/logcharges = stripped_multiline_input(usr, "What have they been charged with?","[id] log charges")
-
- if(!logname || !logcharges)
+ if(occupant == CELL_NONE || crimes == CELL_NONE)
return 0
- occupant = logname
- crimes = logcharges
+
time = timetoset
officer = usr.name
for(var/obj/machinery/computer/prisoner/C in GLOB.prisoncomputer_list)
var/obj/item/paper/P = new /obj/item/paper(C.loc)
- P.name = "[id] log - [logname] [station_time_timestamp()]"
+ P.name = "[id] log - [occupant] [station_time_timestamp()]"
P.info = "
[id] - Brig record
"
P.info += {"
[station_name()] - Security Department
Admission data:
Log generated at: [station_time_timestamp()]
- Detainee: [logname]
+ Detainee: [occupant] Duration: [seconds_to_time(timetoset / 10)]
- Charge(s): [logcharges]
+ Charge(s): [crimes] Arresting Officer: [usr.name]
This log file was generated automatically upon activation of a cell timer."}
playsound(C.loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
GLOB.cell_logs += P
- var/datum/data/record/G = find_record("name", logname, GLOB.data_core.general)
+ var/datum/data/record/G = find_record("name", occupant, GLOB.data_core.general)
var/prisoner_drank = "unknown"
var/prisoner_trank = "unknown"
if(G)
@@ -80,9 +80,9 @@
if(G.fields["real_rank"]) // Ignore alt job titles - necessary for lookups
prisoner_trank = G.fields["real_rank"]
- var/datum/data/record/R = find_security_record("name", logname)
+ var/datum/data/record/R = find_security_record("name", occupant)
- var/announcetext = "Detainee [logname] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of, '[logcharges]'. \
+ var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of: '[crimes]'. \
Arresting Officer: [usr.name].[R ? "" : " Detainee record not found, manual record update required."]"
Radio.autosay(announcetext, name, "Security", list(z))
@@ -91,15 +91,16 @@
if(R)
prisoner = R
- R.fields["criminal"] = "Incarcerated"
+ R.fields["criminal"] = SEC_RECORD_STATUS_INCARCERATED
var/mob/living/carbon/human/M = usr
var/rank = "UNKNOWN RANK"
- if(istype(M) && M.wear_id)
- var/obj/item/card/id/I = M.wear_id
- rank = I.assignment
+ if(istype(M))
+ var/obj/item/card/id/I = M.get_id_card()
+ if(I)
+ rank = I.assignment
if(!R.fields["comments"] || !islist(R.fields["comments"])) //copied from security computer code because apparently these need to be initialized
R.fields["comments"] = list()
- R.fields["comments"] += "Autogenerated by [name] on [GLOB.current_date_string] [station_time_timestamp()] Sentenced to [timetoset/10] seconds for the charges of \"[logcharges]\" by [rank] [usr.name]."
+ R.fields["comments"] += "Autogenerated by [name] on [GLOB.current_date_string] [station_time_timestamp()] Sentenced to [timetoset/10] seconds for the charges of \"[crimes]\" by [rank] [usr.name]."
update_all_mob_security_hud()
return 1
@@ -136,8 +137,7 @@
Radio.config(list("Security" = 0))
Radio.follow_target = src
- pixel_x = ((dir & 3)? (0) : (dir == 4 ? 32 : -32))
- pixel_y = ((dir & 3)? (dir ==1 ? 32 : -32) : (0))
+ set_pixel_offsets_from_dir(32, -32, 32, -32)
spawn(20)
for(var/obj/machinery/door/window/brigdoor/M in GLOB.airlocks)
@@ -175,12 +175,10 @@
if(timing)
if(timeleft() <= 0)
Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security", list(z))
- occupant = "None"
+ occupant = CELL_NONE
timer_end() // open doors, reset timer, clear status screen
timing = 0
. = PROCESS_KILL
-
- updateUsrDialog()
update_icon()
else
timer_end()
@@ -203,8 +201,8 @@
if(!printed)
if(!print_report())
- timing = 0
- return 0
+ timing = FALSE
+ return FALSE
// Set releasetime
releasetime = world.timeofday + timetoset
@@ -237,14 +235,14 @@
return 0
// Reset vars
- occupant = "None"
- crimes = "None"
+ occupant = CELL_NONE
+ crimes = CELL_NONE
time = 0
- officer = "None"
+ officer = CELL_NONE
releasetime = 0
printed = 0
if(prisoner)
- prisoner.fields["criminal"] = "Released"
+ prisoner.fields["criminal"] = SEC_RECORD_STATUS_RELEASED
update_all_mob_security_hud()
prisoner = null
@@ -290,10 +288,11 @@
//Allows AIs to use door_timer, see human attack_hand function below
/obj/machinery/door_timer/attack_ai(mob/user)
- interact(user)
+ attack_hand(user)
+ ui_interact(user)
/obj/machinery/door_timer/attack_ghost(mob/user)
- interact(user)
+ ui_interact(user)
//Allows humans to use door_timer
//Opens dialog window when someone clicks on door timer
@@ -302,98 +301,71 @@
/obj/machinery/door_timer/attack_hand(mob/user)
if(..())
return
- interact(user)
+ ui_interact(user)
-/obj/machinery/door_timer/interact(mob/user)
- // Used for the 'time left' display
- var/second = round(timeleft() % 60)
- var/minute = round((timeleft() - second) / 60)
+/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "brig_timer.tmpl", "Brig Timer", 500, 400)
+ ui.open()
+ ui.set_auto_update(TRUE)
- // Used for 'set timer'
- var/setsecond = round((timetoset / 10) % 60)
- var/setminute = round(((timetoset / 10) - setsecond) / 60)
+/obj/machinery/door_timer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
+ var/data[0]
+ data["cell_id"] = name
+ data["occupant"] = occupant
+ data["crimes"] = crimes
+ data["brigged_by"] = officer
+ data["time_set"] = seconds_to_clock(time / 10)
+ data["time_left"] = seconds_to_clock(timeleft())
+ data["timing"] = timing
+ data["isAllowed"] = allowed(user)
+ data["prisoner_name"] = prisoner_name
+ data["prisoner_charge"] = prisoner_charge
+ data["prisoner_time"] = prisoner_time
- user.set_machine(src)
+ return data
- // dat
- var/dat = "Timer System:"
- dat += " Door [id] controls "
-
- // Start/Stop timer
- if(timing)
- dat += "Stop Timer and open door "
- else
- dat += "Activate Timer and close door "
-
- // Time Left display (uses releasetime)
- dat += "Time Left: [(minute ? text("[minute]:") : null)][second] "
- dat += " "
-
- // Set Timer display (uses timetoset)
- if(timing)
- dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] Set "
- else
- dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] "
-
- // Controls
- dat += "Input Time"
-
- // Mounted flash controls
- for(var/obj/machinery/flasher/F in targets)
- if(F.last_flash && (F.last_flash + 150) > world.time)
- dat += " Flash Charging"
- else
- dat += " Activate Flash"
-
- dat += "
Close"
-
- var/datum/browser/popup = new(user, "door_timer", name, 400, 500)
- popup.set_content(dat)
- popup.open()
-
-
-//Function for using door_timer dialog input, checks if user has permission
-// href_list to
-// "timing" turns on timer
-// "tp" value to modify timer
-// "fc" activates flasher
-// "change" resets the timer to the timetoset amount while the timer is counting down
-// Also updates dialog window and timer icon
/obj/machinery/door_timer/Topic(href, href_list)
- if(..())
- return 1
-
if(!allowed(usr) && !usr.can_admin_interact())
return 1
- usr.set_machine(src)
-
- if(href_list["timing"])
- timing = text2num(href_list["timing"])
-
- if(timing)
- timer_start()
- else
- timer_end()
- if(!isobserver(usr)) //spooky admin ghosts are in your brig, releasing your prisoners
- Radio.autosay("Timer stopped manually by [usr.name].", name, "Security", list(z))
-
- else
- if(href_list["settime"])
- var/time = min(max(round(return_time_input(usr)), 0), 3600)
- timeset(time)
-
- if(href_list["fc"])
- for(var/obj/machinery/flasher/F in targets)
+ if(href_list["flash"])
+ for(var/obj/machinery/flasher/F in targets)
+ if(F.last_flash && (F.last_flash + 150) > world.time)
+ to_chat(usr, "Flash still charging.")
+ else
F.flash()
- if(href_list["change"])
- printed = 1
- timer_start()
+ if(href_list["release"])
+ if(timing)
+ timer_end()
+ Radio.autosay("Timer stopped manually from cell control.", name, "Security", list(z))
+ ui_interact(usr)
- add_fingerprint(usr)
- updateUsrDialog()
- update_icon()
+ if(href_list["prisoner_name"])
+ prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null
+
+ if(href_list["prisoner_charge"])
+ prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null
+
+ if(href_list["prisoner_time"])
+ prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null
+ prisoner_time = min(max(round(prisoner_time), 0), 60)
+
+ if(href_list["set_timer"])
+ if(!prisoner_name || !prisoner_charge || !prisoner_time)
+ return
+ timeset(prisoner_time * 60)
+ occupant = prisoner_name
+ crimes = prisoner_charge
+ prisoner_name = ""
+ prisoner_charge = ""
+ prisoner_time = ""
+ timing = TRUE
+ timer_start()
+ ui_interact(usr)
+ update_icon()
//icon update function
@@ -502,3 +474,4 @@
#undef FONT_COLOR
#undef FONT_STYLE
#undef CHARS_PER_LINE
+#undef CELL_NONE
diff --git a/code/game/machinery/doors/checkForMultipleDoors.dm b/code/game/machinery/doors/checkForMultipleDoors.dm
index d7f66f4630b..7884e3be989 100644
--- a/code/game/machinery/doors/checkForMultipleDoors.dm
+++ b/code/game/machinery/doors/checkForMultipleDoors.dm
@@ -12,5 +12,5 @@
for(var/obj/machinery/door/D in locate(x,y,z))
if(!istype(D, /obj/machinery/door/window) && D.density)
return 0
- //There are no false wall checks because that would be fucking retarded
+ //There are no false wall checks because that would be foolish
return 1
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index fbbe0201d31..2d6fac3bb81 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -204,7 +204,7 @@
. = TRUE
if(operating)
return
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
+ if(!I.use_tool(src, user, 0, volume = 0))
return
try_to_crowbar(user, I)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 448c410c1c8..37dbdb6c9c0 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -419,7 +419,7 @@
if(constructionStep != CONSTRUCTION_WIRES_EXPOSED)
return
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
user.visible_message("[user] starts cutting the wires from [src]...", \
@@ -442,7 +442,7 @@
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
to_chat(user, "There's already a firelock there.")
return
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
user.visible_message("[user] starts bolting down [src]...", \
"You begin bolting [src]...")
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index 6f4a84a7535..c0dce817189 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -59,9 +59,18 @@
/obj/machinery/door/poddoor/try_to_activate_door(mob/user)
return
-/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user)
+/obj/machinery/door/poddoor/try_to_crowbar(mob/user, obj/item/I)
+ if(!density)
+ return
if(!hasPower())
- open()
+ to_chat(user, "You start forcing [src] open...")
+ if(do_after(user, 50 * I.toolspeed, target = src))
+ if(!hasPower())
+ open()
+ else
+ to_chat(user, "[src] resists your efforts to force it!")
+ else
+ to_chat(user, "[src] resists your efforts to force it!")
// Whoever wrote the old code for multi-tile spesspod doors needs to burn in hell. - Unknown
// Wise words. - Bxil
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index 0a0873a2605..a4b9510945a 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -89,13 +89,13 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
/obj/machinery/doppler_array/proc/print_explosive_logs(mob/user)
if(!logged_explosions.len)
- atom_say("No logs currently stored in internal database.")
+ atom_say("No logs currently stored in internal database.")
return
if(active_timers)
to_chat(user, "[src] is already printing something, please wait.")
return
- atom_say("Printing explosive log. Standby...")
- addtimer(CALLBACK(src, .print), 50)
+ atom_say("Printing explosive log. Standby...")
+ addtimer(CALLBACK(src, .proc/print), 50)
/obj/machinery/doppler_array/proc/print()
visible_message("[src] prints a piece of paper!")
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 9beba3f4789..f12361f1664 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -309,13 +309,13 @@ FIRE ALARM
update_icon()
/obj/machinery/firealarm/New(location, direction, building)
- ..()
+ . = ..()
if(building)
buildstage = 0
wiresexposed = TRUE
- pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
- pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
+ setDir(direction)
+ set_pixel_offsets_from_dir(26, -26, 26, -26)
if(is_station_contact(z) && show_alert_level)
if(GLOB.security_level)
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index b7b7e35eef6..37766db58fb 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -58,6 +58,8 @@
playsound(loc, 'sound/weapons/flash.ogg', 100, 1)
flick("[base_state]_flash", src)
+ set_light(2, 1, COLOR_WHITE)
+ addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2)
last_flash = world.time
use_power(1000)
@@ -142,7 +144,7 @@
active = 1
icon_state = "launcheract"
- for(var/obj/machinery/flasher/M in world)
+ for(var/obj/machinery/flasher/M in GLOB.machines)
if(M.id == id)
spawn()
M.flash()
diff --git a/code/game/machinery/guestpass.dm b/code/game/machinery/guestpass.dm
index 2c37a3274c7..165c8dbe4cb 100644
--- a/code/game/machinery/guestpass.dm
+++ b/code/game/machinery/guestpass.dm
@@ -193,5 +193,5 @@
/obj/machinery/computer/guestpass/hop/get_changeable_accesses()
. = ..()
- if(. && ACCESS_CHANGE_IDS in .)
+ if(. && (ACCESS_CHANGE_IDS in .))
return get_all_accesses()
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index fcd6de4020c..6d2586c46aa 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -195,7 +195,7 @@ GLOBAL_LIST_EMPTY(holopads)
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
if(!AI.client)
continue
- to_chat(AI, "Your presence is requested at \the [area].")
+ to_chat(AI, "Your presence is requested at \the [area].")
else
temp = "A request for AI presence was already sent recently. "
temp += "Main Menu"
diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm
index aca4254b517..aa541ec8619 100644
--- a/code/game/machinery/holosign.dm
+++ b/code/game/machinery/holosign.dm
@@ -67,7 +67,7 @@
else
icon_state = "light0"
- for(var/obj/machinery/holosign/M in world)
+ for(var/obj/machinery/holosign/M in GLOB.machines)
if(M.id == src.id)
spawn( 0 )
M.toggle()
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 8d8cabed341..f02e037e8c5 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -116,8 +116,8 @@ Class Procs:
var/panel_open = 0
var/area/myArea
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
- var/use_log = list()
- var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
+ var/list/use_log // Init this list if you wish to add logging to your machine - currently only viewable in VV
+ var/list/settagwhitelist // (Init this list if needed) WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
atom_say_verb = "beeps"
var/siemens_strength = 0.7 // how badly will it shock you?
@@ -224,7 +224,7 @@ Class Procs:
var/obj/item/multitool/P = get_multitool(usr)
if(P && istype(P))
var/update_mt_menu = FALSE
- if("set_tag" in href_list)
+ if("set_tag" in href_list && settagwhitelist)
if(!(href_list["set_tag"] in settagwhitelist))//I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. (seriously though, this is a powerfull HREF, I originally found this loophole, I'm not leaving it in on my PR)
message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name_admin(user)] on [src] (JMP)")
return FALSE
@@ -369,7 +369,6 @@ Class Procs:
/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames.
return
- return 0
/obj/machinery/proc/assign_uid()
uid = gl_uid
@@ -552,14 +551,18 @@ Class Procs:
if(check_records && !R)
threatcount += 4
- if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
- threatcount += 4
+ if(R && R.fields["criminal"])
+ switch(R.fields["criminal"])
+ if(SEC_RECORD_STATUS_EXECUTE)
+ threatcount += 7
+ if(SEC_RECORD_STATUS_ARREST)
+ threatcount += 5
return threatcount
-/obj/machinery/proc/shock(mob/user, prb)
- if(inoperable())
+/obj/machinery/proc/shock(mob/living/user, prb)
+ if(!istype(user) || inoperable())
return FALSE
if(!prob(prb))
return FALSE
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index b73fa94259f..d713817ca06 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -202,7 +202,7 @@
..()
if(autolink)
- for(var/obj/machinery/magnetic_module/M in world)
+ for(var/obj/machinery/magnetic_module/M in GLOB.machines)
if(M.freq == frequency && M.code == code)
magnets.Add(M)
@@ -224,7 +224,7 @@
/obj/machinery/magnetic_controller/process()
if(magnets.len == 0 && autolink)
- for(var/obj/machinery/magnetic_module/M in world)
+ for(var/obj/machinery/magnetic_module/M in GLOB.machines)
if(M.freq == frequency && M.code == code)
magnets.Add(M)
diff --git a/code/game/machinery/portable_tag_turret.dm b/code/game/machinery/portable_tag_turret.dm
index 5d6dc185c83..12bae1bbf5a 100644
--- a/code/game/machinery/portable_tag_turret.dm
+++ b/code/game/machinery/portable_tag_turret.dm
@@ -13,8 +13,8 @@
lasercolor = "b"
installation = /obj/item/gun/energy/laser/tag/blue
-/obj/machinery/porta_turret/tag/New()
- ..()
+/obj/machinery/porta_turret/tag/Initialize(mapload)
+ . = ..()
icon_state = "[lasercolor]grey_target_prism"
/obj/machinery/porta_turret/tag/weapon_setup(var/obj/item/gun/energy/E)
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index b35af581af8..79f1eb83e23 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -87,8 +87,8 @@
lethal = 1
installation = /obj/item/gun/energy/laser
-/obj/machinery/porta_turret/New()
- ..()
+/obj/machinery/porta_turret/Initialize(mapload)
+ . = ..()
if(req_access && req_access.len)
req_access.Cut()
req_one_access = list(ACCESS_SECURITY, ACCESS_HEADS)
@@ -105,8 +105,8 @@
QDEL_NULL(spark_system)
return ..()
-/obj/machinery/porta_turret/centcom/New()
- ..()
+/obj/machinery/porta_turret/centcom/Initialize(mapload)
+ . = ..()
if(req_one_access && req_one_access.len)
req_one_access.Cut()
req_access = list(ACCESS_CENT_SPECOPS)
@@ -520,8 +520,6 @@ GLOBAL_LIST_EMPTY(turret_icons)
/obj/machinery/porta_turret/process()
//the main machinery process
- set background = BACKGROUND_ENABLED
-
if(stat & (NOPOWER|BROKEN))
if(!always_up)
//if the turret has no power or is broken, make the turret pop down if it hasn't already
@@ -1015,8 +1013,8 @@ GLOBAL_LIST_EMPTY(turret_icons)
depotarea.declare_started()
return ..(target)
-/obj/machinery/porta_turret/syndicate/New()
- ..()
+/obj/machinery/porta_turret/syndicate/Initialize(mapload)
+ . = ..()
if(req_one_access && req_one_access.len)
req_one_access.Cut()
req_access = list(ACCESS_SYNDICATE)
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index a17f9dfb9bd..b6da46a67c8 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -177,8 +177,8 @@
F.broken = 0
F.times_used = 0
F.icon_state = "flash"
- if(istype(O,/obj/item/gun/energy/disabler/cyborg))
- var/obj/item/gun/energy/disabler/cyborg/D = O
+ if(istype(O,/obj/item/gun/energy))
+ var/obj/item/gun/energy/D = O
if(D.cell.charge < D.cell.maxcharge)
var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select]
D.cell.give(E.e_cost)
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 081a48c3da1..e4e37ae1bcb 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -19,8 +19,7 @@
var/item_recycle_sound = 'sound/machines/recycler.ogg'
/obj/machinery/recycler/New()
- AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0,
- TRUE, null, null, null, TRUE)
+ AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0, TRUE, null, null, null, TRUE)
..()
component_parts = list()
component_parts += new /obj/item/circuitboard/recycler(null)
@@ -37,7 +36,7 @@
mat_mod *= 50000
for(var/obj/item/stock_parts/manipulator/M in component_parts)
amt_made = 25 * M.rating //% of materials salvaged
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = mat_mod
amount_produced = min(100, amt_made)
@@ -135,7 +134,7 @@
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
I.forceMove(loc)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(I)
if(!material_amount)
qdel(I)
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 095b2e7d56e..85799279ff4 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -59,7 +59,7 @@ GLOBAL_LIST_EMPTY(allRequestConsoles)
var/announceAuth = 0 //Will be set to 1 when you authenticate yourself for announcements
var/msgVerified = "" //Will contain the name of the person who varified it
var/msgStamped = "" //If a message is stamped, this will contain the stamp name
- var/message = "";
+ var/message = ""
var/recipient = ""; //the department which will be receiving the message
var/priority = -1 ; //Priority of the message being sent
light_range = 0
@@ -200,7 +200,7 @@ GLOBAL_LIST_EMPTY(allRequestConsoles)
var/log_msg = message
var/pass = 0
screen = RCS_SENTFAIL
- for(var/obj/machinery/message_server/MS in world)
+ for(var/obj/machinery/message_server/MS in GLOB.machines)
if(!MS.active) continue
MS.send_rc_message(ckey(href_list["department"]),department,log_msg,msgStamped,msgVerified,priority)
pass = 1
@@ -225,7 +225,7 @@ GLOBAL_LIST_EMPTY(allRequestConsoles)
message_log += "Message sent to [recipient] at [station_time_timestamp()] [message]"
Radio.autosay("Alert; a new requests console message received for [recipient] from [department]", null, "[radiochannel]")
else
- audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
+ atom_say("No server detected!")
//Handle screen switching
if(href_list["setScreen"])
@@ -256,7 +256,7 @@ GLOBAL_LIST_EMPTY(allRequestConsoles)
else if(world.time < print_cooldown)
error_message = "Please allow the printer time to prepare the next shipping label."
if(error_message)
- audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: [error_message]'"),,4)
+ atom_say("[error_message]")
return
print_label(ship_tag_name, ship_tag_index)
shipping_log += "Shipping Label printed for [ship_tag_name] [msgVerified]"
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index d0cf38a272d..5952108b6a9 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -20,6 +20,12 @@
account = null
ui_interact(user)
+/obj/machinery/slot_machine/wrench_act(mob/user, obj/item/I)
+ . = TRUE
+ if(!I.tool_use_check(user, 0))
+ return
+ default_unfasten_wrench(user, I)
+
/obj/machinery/slot_machine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 3a6f3011747..da4df4f8382 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -772,6 +772,8 @@
if(usr.stat != 0)
return
+ if(usr.incapacitated() || usr.buckled) //are you cuffed, dying, lying, stunned or other
+ return
if(!state_open)
to_chat(usr, "The unit's doors are shut.")
return
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 6299be7be3d..a5cff57ad52 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -121,7 +121,8 @@
if(user)
to_chat(user, "The connected wire doesn't have enough current.")
return
- for(var/obj/singularity/singulo in GLOB.singularities)
+ for(var/thing in GLOB.singularities)
+ var/obj/singularity/singulo = thing
if(singulo.z == z)
singulo.target = src
icon_state = "[icontype]1"
@@ -132,7 +133,8 @@
/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user = null)
- for(var/obj/singularity/singulo in world)
+ for(var/thing in GLOB.singularities)
+ var/obj/singularity/singulo = thing
if(singulo.target == src)
singulo.target = null
icon_state = "[icontype]0"
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 99642db320e..181d5e494da 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -77,11 +77,10 @@
update_icon()
try_detonate(TRUE)
//Counter terrorists win
- else if(!active || defused)
- if(defused && payload in src)
+ else if(defused)
+ active = FALSE
+ if(payload in src)
payload.defuse()
- countdown.stop()
- STOP_PROCESSING(SSfastprocess, src)
/obj/machinery/syndicatebomb/New()
wires = new(src)
@@ -244,7 +243,7 @@
/obj/machinery/syndicatebomb/proc/settings(mob/user)
var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(can_interact(user)) //No running off and setting bombs from across the station
- timer_set = Clamp(new_timer, minimum_timer, maximum_timer)
+ timer_set = clamp(new_timer, minimum_timer, maximum_timer)
loc.visible_message("[bicon(src)] timer set for [timer_set] seconds.")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && can_interact(user))
if(defused || active)
diff --git a/code/game/machinery/tcomms/_base.dm b/code/game/machinery/tcomms/_base.dm
new file mode 100644
index 00000000000..05c7552aacc
--- /dev/null
+++ b/code/game/machinery/tcomms/_base.dm
@@ -0,0 +1,496 @@
+/*
+
+ ParadiseSS13 Telecommunications System
+
+ Rewritten from the ground up because I was totally unhappy with how laggy and complicated the current implementation was
+ The system is made up of two objects. A main core and relays.
+
+ The main core is basically the same as all of the machines from the previous implementation, apart from the relay
+ The core handles recieving and sending messages, logging messages, the NTTC configuration, and serves as the linkage hub for relays
+
+ Relays function much in the same way as the old ones. They just expand the reach of tcomms from one z-level to another.
+
+ This file contains extra datums and helper procs which the system utilises.
+ Unlike old telecomms, everything in here **should** be well documented. If not, feel free to add your own
+ -aa07
+
+*/
+
+/// Global list for all telecomms machines in the world
+GLOBAL_LIST_EMPTY(tcomms_machines)
+
+/**
+ * # Telecommunications Device
+ *
+ * This is the base machine for both tcomms devices (core + relay)
+ *
+ * This holds a few base procs (Icon updates, enable/disable, etc)
+ * It also has the initial overrides for Initialize() and Destroy()
+ */
+/obj/machinery/tcomms
+ name = "Telecommunications Device"
+ desc = "Someone forgot to say what this thingy does. Please yell at a coder"
+ icon = 'icons/obj/tcomms.dmi'
+ icon_state = "error"
+ density = TRUE
+ anchored = TRUE
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 500
+ /// Network ID used for names + auto linkage
+ var/network_id = "None"
+ /// Is the machine active
+ var/active = TRUE
+ /// Has the machine been hit by an ionspheric anomalie
+ var/ion = FALSE
+
+/**
+ * Base Initializer
+ *
+ * Ensures that the machine is put into the global list of tcomms devices, and then its made sure that the icon is correct if the machine starts offline
+ */
+/obj/machinery/tcomms/Initialize(mapload)
+ . = ..()
+ GLOB.tcomms_machines += src
+ update_icon()
+ if((!mapload) && (usr))
+ // To the person who asks "Hey affected, why are you using this massive operator when you can use AREACOORD?" Well, ill tell you
+ // get_area_name is fucking broken and uses a for(x in world) search
+ // It doesnt even work, is expensive, and returns 0
+ // Im not refactoring one thing which could risk breaking all admin location logs
+ // Fight me
+ log_action(usr, "constructed a new [src] at [src ? "[get_location_name(src, TRUE)] [COORD(src)]" : "nonexistent location"] [ADMIN_JMP(src)]", adminmsg = TRUE)
+ // Add in component parts for the sake of deconstruction
+ component_parts = list()
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+
+/**
+ * Base Destructor
+ *
+ * Ensures that the machine is taken out of the global list when destroyed
+ */
+/obj/machinery/tcomms/Destroy()
+ GLOB.tcomms_machines -= src
+ if(usr)
+ log_action(usr, "destroyed a [src] at [src ? "[get_location_name(src, TRUE)] [COORD(src)]" : "nonexistent location"] [ADMIN_JMP(src)]", adminmsg = TRUE)
+ return ..()
+
+/**
+ * Icon Updater
+ *
+ * Ensures that the icon updates properly based on if the machine is active or not. This removes the need for this check in many other places.
+ */
+/obj/machinery/tcomms/update_icon()
+ . = ..()
+ // Show the off sprite if were inactive, ion'd or unpowered
+ if(!active || (stat & NOPOWER) || ion)
+ icon_state = "[initial(icon_state)]_off"
+ else
+ icon_state = initial(icon_state)
+
+
+// Attack overrides. These are needed so the UIs can be opened up //
+/obj/machinery/tcomms/attack_ai(mob/user)
+ add_hiddenprint(user)
+ ui_interact(user)
+
+/obj/machinery/tcomms/attack_ghost(mob/user)
+ ui_interact(user)
+
+/obj/machinery/tcomms/attack_hand(mob/user)
+ if(..(user))
+ return
+ ui_interact(user)
+
+
+/**
+ * Start of Ion Anomalie Event
+ *
+ * Proc to easily start an Ion Anomalie's effects, and update the icon
+ */
+/obj/machinery/tcomms/proc/start_ion()
+ ion = TRUE
+ update_icon()
+
+/**
+ * End of Ion Anomalie Event
+ *
+ * Proc to easily stop an Ion Anomalie's effects, and update the icon
+ */
+/obj/machinery/tcomms/proc/end_ion()
+ ion = FALSE
+ update_icon()
+
+/**
+ * Logging helper
+ *
+ * Proc which allows easy logging of changs made to tcomms machines
+ * Arguments:
+ * * user - The user who did the action
+ * * msg - The log message
+ * * adminmsg - Should an admin log be sent when this happens
+ */
+/obj/machinery/tcomms/proc/log_action(user, msg, adminmsg = FALSE)
+ log_game("NTTC: [key_name(user)] [msg]")
+ log_investigate("[key_name(user)] [msg]", "nttc")
+ if(adminmsg)
+ message_admins("[key_name_admin(user)] [msg]")
+/**
+ * Power Change Handler
+ *
+ * Proc which ensures icons are updated when machines lose power
+ */
+/obj/machinery/tcomms/power_change()
+ ..()
+ update_icon()
+
+/**
+ * # Telecommunications Message
+ *
+ * Datum which holds all the data for a message being sent
+ *
+ * This used to be a single associative list with just keys and values
+ * It had no typepath or presence checking, and was absolutely awful to work with
+ * This fixes that
+ *
+ */
+/datum/tcomms_message
+ /// Who sent the message
+ var/sender_name = "Error"
+ /// What job are they
+ var/sender_job = "Error"
+ /// Pieces of the message
+ var/list/message_pieces = list()
+ /// Source Z-level
+ var/source_level = 0
+ /// What frequency the message is sent on
+ var/freq = 0
+ /// Was it sent with a voice changer
+ var/vmask = FALSE
+ /// Did the signal come from a device that requires tcomms to function
+ var/needs_tcomms = TRUE
+ /// Origin of the signal
+ var/datum/radio_frequency/connection
+ /// Who sent it
+ var/mob/sender
+ /// The radio it was sent from
+ var/obj/item/radio/radio
+ /// The signal data (See defines/radio.dm)
+ var/data
+ /// Verbage used
+ var/verbage = "says"
+ /// Follow target for AI use
+ var/atom/follow_target = null
+ /// Is this signal meant to be rejected
+ var/reject = FALSE
+ /// Voice name if the person doesnt have a name (diona, alien, etc)
+ var/vname
+ /// List of all channels this can be sent or recieved on
+ var/list/zlevels = list()
+ /// Should this signal be re-broadcasted (Can be modified by NTTC, defaults to TRUE)
+ var/pass = TRUE
+
+/**
+ * Destructor for the TCM datum.
+ *
+ * This needs to happen like this so that things dont keep references held in place
+ */
+/datum/tcomms_message/Destroy()
+ connection = null
+ radio = null
+ follow_target = null
+ return ..()
+
+
+#define CREW_RADIO_TYPE 0
+#define CENTCOMM_RADIO_TYPE 1
+#define SYNDICATE_RADIO_TYPE 2
+
+/**
+ * Connection checker
+ *
+ * Checks the connection frequency against the intended frequency for the message
+ * NOTE: I barely know what on earth this does, but it works and it scares me
+ * Arguments:
+ * * old_freq - Frequency of the connection
+ * * new_freq - Frequency of the message
+ */
+/proc/is_bad_connection(old_freq, new_freq)
+ var/old_type = CREW_RADIO_TYPE
+ var/new_type = CREW_RADIO_TYPE
+ for(var/antag_freq in SSradio.ANTAG_FREQS)
+ if(old_freq == antag_freq)
+ old_type = SYNDICATE_RADIO_TYPE
+ if(new_freq == antag_freq)
+ new_type = SYNDICATE_RADIO_TYPE
+
+ for(var/cent_freq in SSradio.CENT_FREQS)
+ if(old_freq == cent_freq)
+ old_type = CENTCOMM_RADIO_TYPE
+ if(new_freq == cent_freq)
+ new_type = CENTCOMM_RADIO_TYPE
+
+ return new_type > old_type
+
+#undef CREW_RADIO_TYPE
+#undef CENTCOMM_RADIO_TYPE
+#undef SYNDICATE_RADIO_TYPE
+
+
+/**
+ * Message Broadcast Proc
+ *
+ * This big fat disaster is responsible for sending the message out to all headsets and radios on the station
+ * It is absolutely disgusting, but used to take about 20 arguments before I slimmed it down to just one
+ * Arguments:
+ * * tcm - The tcomms message datum
+ */
+/proc/broadcast_message(datum/tcomms_message/tcm)
+
+
+ /* ###### Prepare the radio connection ###### */
+
+ var/display_freq = tcm.freq
+
+ var/bad_connection = FALSE
+ var/datum/radio_frequency/new_connection = tcm.connection
+
+ if(tcm.connection.frequency != display_freq)
+ bad_connection = is_bad_connection(tcm.connection.frequency, display_freq)
+ new_connection = SSradio.return_frequency(display_freq)
+
+ var/list/radios = list()
+
+ // --- Broadcast only to intercom devices ---
+
+ if(tcm.data == SIGNALTYPE_INTERCOM && !bad_connection)
+
+ for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"])
+ if(R.receive_range(display_freq, tcm.zlevels) > -1)
+ radios += R
+
+ // --- Broadcast only to intercoms and station-bounced radios ---
+
+ else if(tcm.data == SIGNALTYPE_INTERCOM_SBR && !bad_connection)
+
+ for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"])
+
+ if(istype(R, /obj/item/radio/headset))
+ continue
+
+ if(R.receive_range(display_freq, tcm.zlevels) > -1)
+ radios += R
+
+ // --- Broadcast to ALL radio devices ---
+
+ else if(!bad_connection)
+
+ for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"])
+ if(R.receive_range(display_freq, tcm.zlevels) > -1)
+ radios += R
+
+ // Add syndie radios for intercepts if its a regular department frequency
+ for(var/antag_freq in SSradio.ANTAG_FREQS)
+ var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq)
+ for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"])
+ if(R.receive_range(antag_freq, tcm.zlevels) > -1)
+ // Only add if it wasnt there already
+ radios |= R
+
+ // Get a list of mobs who can hear from the radios we collected.
+ var/list/receive = get_mobs_in_radio_ranges(radios)
+
+ /* ###### Organize the receivers into categories for displaying the message ###### */
+
+ // Understood the message:
+ var/list/heard_masked = list() // masked name or no real name
+ var/list/heard_normal = list() // normal message
+
+ // Did not understand the message:
+ var/list/heard_voice = list() // voice message (ie "chimpers")
+ var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
+ var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
+
+ for(var/M in receive)
+ var/mob/R = M
+
+ /* --- Loop through the receivers and categorize them --- */
+
+ if(is_admin(R) && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
+ continue
+
+ if(isnewplayer(R)) // we don't want new players to hear messages. rare but generates runtimes.
+ continue
+
+ // --- Can understand the speech ---
+ if(!tcm.sender || R.say_understands(tcm.sender))
+
+ // - Not human or wearing a voice mask -
+ if(!tcm.sender || !ishuman(tcm.sender) || tcm.vmask)
+ heard_masked += R
+
+ // - Human and not wearing voice mask -
+ else
+ heard_normal += R
+
+ // --- Can't understand the speech ---
+
+ else
+ // - Just display a garbled message -
+ heard_garbled += R
+
+
+ /* ###### Begin formatting and sending the message ###### */
+ if(length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
+
+ /* --- Some miscellaneous variables to format the string output --- */
+ var/freq_text = get_frequency_name(display_freq)
+
+ var/part_b_extra = ""
+ var/part_a = "\[[freq_text]\][part_b_extra]" // goes in the actual output
+
+ // --- Some more pre-message formatting ---
+ var/part_b = "" // Tweaked for security headsets -- TLE
+ var/part_c = ""
+
+
+ // --- Filter the message; place it in quotes apply a verb ---
+ var/quotedmsg = null
+ if(tcm.sender)
+ quotedmsg = "[tcm.sender.say_quote(multilingual_to_message(tcm.message_pieces))], \"[multilingual_to_message(tcm.message_pieces)]\""
+ else
+ quotedmsg = "says, \"[multilingual_to_message(tcm.message_pieces)]\""
+
+ // --- This following recording is intended for research and feedback in the use of department radio channels ---
+
+ var/part_blackbox_b = " \[[freq_text]\]" // Tweaked for security headsets -- TLE
+ var/blackbox_msg = "[part_a][tcm.sender_name][part_blackbox_b][quotedmsg][part_c]"
+ //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
+
+ //BR.messages_admin += blackbox_admin_msg
+ if(istype(GLOB.blackbox))
+ switch(display_freq)
+ if(PUB_FREQ)
+ GLOB.blackbox.msg_common += blackbox_msg
+ if(SCI_FREQ)
+ GLOB.blackbox.msg_science += blackbox_msg
+ if(COMM_FREQ)
+ GLOB.blackbox.msg_command += blackbox_msg
+ if(MED_FREQ)
+ GLOB.blackbox.msg_medical += blackbox_msg
+ if(ENG_FREQ)
+ GLOB.blackbox.msg_engineering += blackbox_msg
+ if(SEC_FREQ)
+ GLOB.blackbox.msg_security += blackbox_msg
+ if(DTH_FREQ)
+ GLOB.blackbox.msg_deathsquad += blackbox_msg
+ if(SYND_FREQ)
+ GLOB.blackbox.msg_syndicate += blackbox_msg
+ if(SYNDTEAM_FREQ)
+ GLOB.blackbox.msg_syndteam += blackbox_msg
+ if(SUP_FREQ)
+ GLOB.blackbox.msg_cargo += blackbox_msg
+ if(SRV_FREQ)
+ GLOB.blackbox.msg_service += blackbox_msg
+ else
+ GLOB.blackbox.messages += blackbox_msg
+ //End of research and feedback code.
+
+ /* ###### Send the message ###### */
+
+
+ /* --- Process all the mobs that heard a masked voice (understood) --- */
+
+ if(length(heard_masked))
+ for(var/M in heard_masked)
+ var/mob/R = M
+ R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 0, tcm.sender_name, follow_target=tcm.follow_target)
+
+ /* --- Process all the mobs that heard the voice normally (understood) --- */
+
+ if(length(heard_normal))
+ for(var/M in heard_normal)
+ var/mob/R = M
+ R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 0, tcm.sender_name, follow_target=tcm.follow_target)
+
+ /* --- Process all the mobs that heard the voice normally (did not understand) --- */
+
+ if(length(heard_voice))
+ for(var/M in heard_voice)
+ var/mob/R = M
+ R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender,0, tcm.vname, follow_target=tcm.follow_target)
+
+ /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
+ // Displays garbled message (ie "f*c* **u, **i*er!")
+
+ if(length(heard_garbled))
+ for(var/M in heard_garbled)
+ var/mob/R = M
+ R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 1, tcm.vname, follow_target=tcm.follow_target)
+
+
+ /* --- Complete gibberish. Usually happens when there's a compressed message --- */
+
+ if(length(heard_gibberish))
+ for(var/M in heard_gibberish)
+ var/mob/R = M
+ R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 1, follow_target=tcm.follow_target)
+
+ return TRUE
+
+
+/**
+ * # Telecommunications Password Paper
+ *
+ * Piece of paper that spawns with the default link password
+ *
+ * This is spawned in the CE office and has the default link password
+ * While convenient, this is not necessary and doesnt matter if it gets lost or destroyed
+ * Because you can view the password easily by just looking at the core link page
+ */
+/obj/item/paper/tcommskey
+ name = "Telecommunications linkage password"
+
+/**
+ * Password Paper Initializer
+ *
+ * This paper MUST be LateInitialized so the core has a chance to initialize and setup its password
+ * Otherwise shit breaks BADLY
+ */
+/obj/item/paper/tcommskey/Initialize(mapload)
+ return INITIALIZE_HINT_LATELOAD
+
+/**
+ * Password Paper Late Initializer
+ *
+ * Since the core was regularly initialized, we can now use the LateInitialize here to grab its password, then put it on paper
+ */
+/obj/item/paper/tcommskey/LateInitialize(mapload)
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ if(C.network_id == "STATION-CORE")
+ info = "
Telecommunications Key
\n\t The station core linkage password is '[C.link_password]'. Should this paper be misplaced or destroyed, fear not, as the password is visible under the core linkage section. Should you wish to modify this password, it can be modified from the core."
+ info_links = info
+ update_icon()
+ // Save time, even though there should only be one STATION-CORE in the world
+ break
+ return ..()
+
+/**
+ * Screwdriver Act Handler
+ *
+ * Handles the screwdriver action for all tcomms machines, so they can be open and closed to be deconstructed
+ */
+/obj/machinery/tcomms/screwdriver_act(mob/user, obj/item/I)
+ . = TRUE
+ default_deconstruction_screwdriver(user, icon_state, icon_state, I)
+
+/**
+ * Crowbar Act Handler
+ *
+ * Handles the crowbar action for all tcomms machines, so they can be deconstructed
+ */
+/obj/machinery/tcomms/crowbar_act(mob/user, obj/item/I)
+ . = TRUE
+ default_deconstruction_crowbar(user, I)
diff --git a/code/game/machinery/tcomms/core.dm b/code/game/machinery/tcomms/core.dm
new file mode 100644
index 00000000000..46cd0e6df71
--- /dev/null
+++ b/code/game/machinery/tcomms/core.dm
@@ -0,0 +1,305 @@
+#define UI_TAB_CONFIG "CONFIG"
+#define UI_TAB_LINKS "LINKS"
+#define UI_TAB_FILTER "FILTER"
+
+/**
+ * # Telecommunications Core
+ *
+ * The core of the entire telecomms operation
+ *
+ * This thing basically handles the main broadcasting of the data, as well as NTTC configs
+ * The relays dont do any actual processing, they are just objects which can bring tcomms to another zlevel
+ */
+/obj/machinery/tcomms/core
+ name = "Telecommunications Core"
+ desc = "A large rack full of communications equipment. Looks important."
+ icon_state = "core"
+ /// The NTTC config for this device
+ var/datum/nttc_configuration/nttc = new()
+ /// List of all reachable devices
+ var/list/reachable_zlevels = list()
+ /// List of all linked relays
+ var/list/linked_relays = list()
+ /// Password for linking stuff together
+ var/link_password
+ /// What tab of the UI were currently on
+ var/ui_tab = UI_TAB_CONFIG
+
+/**
+ * Initializer for the core.
+ *
+ * Calls parent to ensure its added to the GLOB of tcomms machines, before generating a link password and adding itself to the list of reachable Zs.
+ */
+/obj/machinery/tcomms/core/Initialize(mapload)
+ . = ..()
+ link_password = GenerateKey()
+ reachable_zlevels |= loc.z
+ component_parts += new /obj/item/circuitboard/tcomms/core(null)
+
+/**
+ * Destructor for the core.
+ *
+ * Ensures that the machine is taken out of the global list when destroyed, and also unlinks all connected relays
+ */
+/obj/machinery/tcomms/core/Destroy()
+ for(var/obj/machinery/tcomms/relay/R in linked_relays)
+ R.Reset()
+ QDEL_NULL(nttc) // Delete the NTTC datum
+ linked_relays.Cut() // Just to be sure
+ return ..()
+
+/**
+ * Helper to see if a zlevel is reachable
+ *
+ * This is a simple check to see if the input z-level is in the list of reachable ones
+ * Returns TRUE if it can, FALSE if it cant
+ *
+ * Arguments:
+ * * zlevel - The input z level to test
+ */
+/obj/machinery/tcomms/core/proc/zlevel_reachable(zlevel)
+ // Nothing is reachable if the core is offline, unpowered, or ion'd
+ if(!active || (stat & NOPOWER) || ion)
+ return FALSE
+ if(zlevel in reachable_zlevels)
+ return TRUE
+ else
+ return FALSE
+
+/**
+ * Proc which takes in the message datum
+ *
+ * Some checks are ran on the signal, and NTTC is applied
+ * After that, it is broadcasted out to the required Z-levels
+ *
+ * Arguments:
+ * * tcm - The tcomms message datum
+ */
+/obj/machinery/tcomms/core/proc/handle_message(datum/tcomms_message/tcm)
+ // Don't do anything with rejected signals, if were offline, if we are ion'd, or if we have no power
+ if(tcm.reject || !active || (stat & NOPOWER) || ion)
+ return FALSE
+ // Kill the signal if its on a z-level that isnt reachable
+ if(!zlevel_reachable(tcm.source_level))
+ return FALSE
+
+ // Now we can run NTTC
+ tcm = nttc.modify_message(tcm)
+
+ // If the signal shouldnt be broadcast, dont broadcast it
+ if(!tcm.pass)
+ // We still return TRUE here because the signal was handled, even though we didnt broadcast
+ return TRUE
+
+ // Now we generate the list of where that signal should go to
+ tcm.zlevels = reachable_zlevels
+ tcm.zlevels |= tcm.source_level
+
+ // Now check if they actually have pieces, if so, broadcast
+ if(tcm.message_pieces)
+ broadcast_message(tcm)
+ return TRUE
+
+ return FALSE
+
+/**
+ * Proc to remake the list of available zlevels
+ *
+ * Loops through the list of connected relays and adds their zlevels in.
+ * This is called if a relay is added or removed
+ *
+ */
+/obj/machinery/tcomms/core/proc/refresh_zlevels()
+ // Refresh the list
+ reachable_zlevels = list()
+ // Add itself as a reachable Z-level
+ reachable_zlevels |= loc.z
+ // Add all the linked relays in
+ for(var/obj/machinery/tcomms/relay/R in linked_relays)
+ // Only if the relay is active
+ if(R.active && !(R.stat & NOPOWER))
+ reachable_zlevels |= R.loc.z
+
+
+//////////////
+// UI STUFF //
+//////////////
+
+/obj/machinery/tcomms/core/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ // this is silly but it has to be done because NTTC inits before languages do
+ if(nttc.valid_languages.len == 1)
+ nttc.update_languages()
+
+ // Now the actual UI stuff
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "tcomms_core.tmpl", "Telecommunications Core", 900, 600)
+ ui.open()
+ ui.set_auto_update(1)
+
+/obj/machinery/tcomms/core/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
+ var/data[0]
+ // What tab are we on
+ data["tab"] = ui_tab
+ data["ion"] = ion
+
+ // Only send NTTC settings if were on the right tab. This saves on sending overhead.
+ if(ui_tab == UI_TAB_CONFIG)
+ // Z-level list. Note that this will also show sectors with hidden relay links, but you cant see the relays themselves
+ // This allows the crew to realise that sectors have hidden relays
+ data["sectors_available"] = "Count: [length(reachable_zlevels)] | List: [jointext(reachable_zlevels, " ")]"
+ // Toggles
+ data["active"] = active
+ data["nttc_toggle_jobs"] = nttc.toggle_jobs
+ data["nttc_toggle_job_color"] = nttc.toggle_job_color
+ data["nttc_toggle_name_color"] = nttc.toggle_name_color
+ data["nttc_toggle_command_bold"] = nttc.toggle_command_bold
+ // Strings
+ data["nttc_setting_language"] = nttc.setting_language
+ data["nttc_job_indicator_type"] = nttc.job_indicator_type
+ // Network ID
+ data["network_id"] = network_id
+
+ if(ui_tab == UI_TAB_LINKS)
+ data["link_password"] = link_password
+ // You ready to see some shit?
+ for(var/obj/machinery/tcomms/relay/R in linked_relays)
+ // Dont show relays with a hidden link
+ if(R.hidden_link)
+ continue
+ // Assume false
+ var/status = FALSE
+ var/status_color = "'background-color: #eb4034'" // Red
+ if(R.active && !(R.stat & NOPOWER))
+ status = TRUE
+ status_color = "'background-color: #32a852'" // Green
+
+
+
+ data["entries"] += list(list("addr" = "\ref[R]", "net_id" = R.network_id, "sector" = R.loc.z, "status" = status, "status_color" = status_color))
+ // End the shit
+
+ if(ui_tab == UI_TAB_FILTER)
+ data["filtered_users"] = nttc.filtering
+
+ return data
+
+/obj/machinery/tcomms/core/Topic(href, href_list)
+ // Check against href exploits
+ if(..())
+ return
+
+ if(href_list["tab"])
+ // Make sure its a valid tab
+ if(href_list["tab"] in list(UI_TAB_CONFIG, UI_TAB_LINKS, UI_TAB_FILTER))
+ ui_tab = href_list["tab"]
+
+ // Check if they did a href, but only for that current tab
+ if(ui_tab == UI_TAB_CONFIG)
+ // All the toggle on/offs go here
+ if(href_list["toggle_active"])
+ active = !active
+ update_icon()
+ // NTTC Toggles
+ if(href_list["nttc_toggle_jobs"])
+ nttc.toggle_jobs = !nttc.toggle_jobs
+ log_action(usr, "toggled job tags (Now [nttc.toggle_jobs])")
+ if(href_list["nttc_toggle_job_color"])
+ nttc.toggle_job_color = !nttc.toggle_job_color
+ log_action(usr, "toggled job colors (Now [nttc.toggle_job_color])")
+ if(href_list["nttc_toggle_name_color"])
+ nttc.toggle_name_color = !nttc.toggle_name_color
+ log_action(usr, "toggled name colors (Now [nttc.toggle_name_color])")
+ if(href_list["nttc_toggle_command_bold"])
+ nttc.toggle_command_bold = !nttc.toggle_command_bold
+ log_action(usr, "toggled command bold (Now [nttc.toggle_command_bold])")
+ // We need to be a little more fancy for the others
+
+ // Job Format
+ if(href_list["nttc_job_indicator_type"])
+ var/card_style = input(usr, "Pick a job card format.", "Job Card Format") as null|anything in nttc.job_card_styles
+ if(!card_style)
+ return
+ nttc.job_indicator_type = card_style
+ to_chat(usr, "Jobs will now have the style of [card_style].")
+ log_action(usr, "has set NTTC job card format to [card_style]")
+
+ // Language Settings
+ if(href_list["nttc_setting_language"])
+ var/new_language = input(usr, "Pick a language to convert messages to.", "Language Conversion") as null|anything in nttc.valid_languages
+ if(!new_language)
+ return
+ if(new_language == "--DISABLE--")
+ nttc.setting_language = null
+ to_chat(usr, "Language conversion disabled.")
+ else
+ nttc.setting_language = new_language
+ to_chat(usr, "Messages will now be converted to [new_language].")
+
+ log_action(usr, new_language == "--DISABLE--" ? "disabled NTTC language conversion" : "set NTTC language conversion to [new_language]", TRUE)
+
+ // Imports and exports
+ if(href_list["import"])
+ var/json = input(usr, "Provide configuration JSON below.", "Load Config", nttc.nttc_serialize()) as message
+ if(nttc.nttc_deserialize(json, usr.ckey))
+ log_action(usr, "has uploaded a NTTC JSON configuration: [ADMIN_SHOWDETAILS("Show", json)]", TRUE)
+
+ if(href_list["export"])
+ usr << browse(nttc.nttc_serialize(), "window=save_nttc")
+
+ // Set network ID
+ if(href_list["network_id"])
+ var/new_id = input(usr, "Please enter a new network ID", "Network ID", network_id)
+ log_action(usr, "renamed core with ID [network_id] to [new_id]")
+ to_chat(usr, "Device ID changed from [network_id] to [new_id].")
+ network_id = new_id
+
+ if(ui_tab == UI_TAB_LINKS)
+ if(href_list["unlink"])
+ var/obj/machinery/tcomms/relay/R = locate(href_list["unlink"])
+ if(istype(R, /obj/machinery/tcomms/relay))
+ var/confirm = alert("Are you sure you want to unlink this relay?\nID: [R.network_id]\nADDR: \ref[R]", "Relay Unlink", "Yes", "No")
+ if(confirm == "Yes")
+ log_action(usr, "has unlinked tcomms relay with ID [R.network_id] from tcomms core with ID [network_id]", TRUE)
+ R.Reset()
+ else
+ to_chat(usr, "ERROR: Relay not found. Please file an issue report.")
+
+ if(href_list["change_password"])
+ var/new_password = input(usr, "Please enter a new password","New Password", link_password)
+ log_action(usr, "has changed the password on core with ID [network_id] from [link_password] to [new_password]")
+ to_chat(usr, "Successfully changed password from [link_password] to [new_password].")
+ link_password = new_password
+
+ if(ui_tab == UI_TAB_FILTER)
+ if(href_list["add_filter"])
+ // This is a stripped input because I did NOT come this far for this system to be abused by HTML injection
+ var/name_to_add = stripped_input(usr, "Enter a name to add to the filtering list", "Name Entry")
+ if(name_to_add == "")
+ return
+ if(name_to_add in nttc.filtering)
+ to_chat(usr, "ERROR: User already in filtering list.")
+ else
+ nttc.filtering |= name_to_add
+ log_action(usr, "has added [name_to_add] to the NTTC filter list on core with ID [network_id]", TRUE)
+ to_chat(usr, "Successfully added [name_to_add] to the NTTC filtering list.")
+
+
+ if(href_list["remove_filter"])
+ var/name_to_remove = href_list["remove_filter"]
+ if(!(name_to_remove in nttc.filtering))
+ to_chat(usr, "ERROR: Name does not exist in filter list. Please file an issue report.")
+ else
+ var/confirm = alert(usr, "Are you sure you want to remove [name_to_remove] from the filtering list?", "Confirm Removal", "Yes", "No")
+ if(confirm == "Yes")
+ nttc.filtering -= name_to_remove
+ log_action(usr, "has removed [name_to_remove] from the NTTC filter list on core with ID [network_id]", TRUE)
+ to_chat(usr, "Successfully removed [name_to_remove] from the NTTC filtering list.")
+
+
+ // Hack to speed update the nanoUI
+ SSnanoui.update_uis(src)
+
+#undef UI_TAB_CONFIG
+#undef UI_TAB_LINKS
+#undef UI_TAB_FILTER
diff --git a/code/game/machinery/tcomms/nttc.dm b/code/game/machinery/tcomms/nttc.dm
new file mode 100644
index 00000000000..cd880970b23
--- /dev/null
+++ b/code/game/machinery/tcomms/nttc.dm
@@ -0,0 +1,295 @@
+/*
+ NTTC system
+ This is basically the replacement for NTSL and allows tickbox features such as job titles and colours, without needing a script
+ This also means that there is no user input here, which means the system isnt prone to exploits since its only selecting options, no user input
+ Basically, just imagine pfSense for tcomms
+
+ All this code was written by Tigercat2000. I take no credit -aa07
+*/
+
+#define JOB_STYLE_1 "Name (Job)"
+#define JOB_STYLE_2 "Name - Job"
+#define JOB_STYLE_3 "\[Job\] Name"
+#define JOB_STYLE_4 "(Job) Name"
+
+/datum/nttc_configuration
+ var/regex/word_blacklist = new("( [ckey] attempted to upload an NTTC configuration containing JS abusable tags!")
+ log_admin("EXPLOIT WARNING: [ckey] attempted to upload an NTTC configuration containing JS abusable tags")
+ return FALSE
+ var/list/var_list = json_decode(text)
+ for(var/variable in var_list)
+ if(variable in to_serialize) // Don't just accept any random vars jesus christ!
+ var/sanitize_method = serialize_sanitize[variable]
+ var/variable_value = var_list[variable]
+ variable_value = nttc_sanitize(variable_value, sanitize_method)
+ if(variable_value != null)
+ vars[variable] = variable_value
+ return TRUE
+
+// Sanitizing user input. Don't blindly trust the JSON.
+/datum/nttc_configuration/proc/nttc_sanitize(variable, sanitize_method)
+ if(!sanitize_method)
+ return null
+
+ switch(sanitize_method)
+ if("bool")
+ return variable ? TRUE : FALSE
+ // if("table", "array")
+ if("array")
+ if(!islist(variable))
+ return list()
+ // Insert html filtering for the regexes here if you're boring
+ var/newlist = json_decode(html_decode(json_encode(variable)))
+ if(!islist(newlist))
+ return null
+ return newlist
+ if("string")
+ return "[variable]"
+
+ return variable
+
+// Primary signal modification. This is where all of the variables behavior are actually implemented.
+/datum/nttc_configuration/proc/modify_message(datum/tcomms_message/tcm)
+ // Check if they should be blacklisted right off the bat. We can save CPU if the message wont even be processed
+ if(tcm.sender_name in filtering)
+ tcm.pass = FALSE
+ // All job and coloring shit
+ if(toggle_job_color || toggle_name_color)
+ var/job = tcm.sender_job
+ job_class = all_jobs[job]
+
+ if(toggle_name_color)
+ var/new_name = "" + tcm.sender_name + ""
+ tcm.sender_name = new_name
+ tcm.vname = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on
+
+ if(toggle_jobs)
+ var/new_name = ""
+ var/job = tcm.sender_job
+ if(job in ert_jobs)
+ job = "ERT"
+ if(toggle_job_color)
+ switch(job_indicator_type)
+ // These must have trailing spaces. No exceptions.
+ if(JOB_STYLE_1)
+ new_name = "[tcm.sender_name] ([job]) "
+ if(JOB_STYLE_2)
+ new_name = "[tcm.sender_name] - [job] "
+ if(JOB_STYLE_3)
+ new_name = "\[[job]\] [tcm.sender_name] "
+ if(JOB_STYLE_4)
+ new_name = "([job]) [tcm.sender_name] "
+ else
+ switch(job_indicator_type)
+ if(JOB_STYLE_1)
+ new_name = "[tcm.sender_name] ([job]) "
+ if(JOB_STYLE_2)
+ new_name = "[tcm.sender_name] - [job] "
+ if(JOB_STYLE_3)
+ new_name = "\[[job]\] [tcm.sender_name] "
+ if(JOB_STYLE_4)
+ new_name = "([job]) [tcm.sender_name] "
+
+ // Only change the name if they have a job tag set, otherwise everyone becomes unknown, and thats bad
+ if(new_name != "")
+ tcm.sender_name = new_name
+ tcm.vname = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on
+ // This is hacky stuff for multilingual messages...
+ var/list/message_pieces = tcm.message_pieces
+
+ // Makes heads of staff bold
+ if(toggle_command_bold)
+ var/job = tcm.sender_job
+ if((job in ert_jobs) || (job in heads))
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ S.message = "[capitalize(S.message)]" // This only capitalizes the first word
+
+ // Language Conversion
+ if(setting_language && valid_languages[setting_language])
+ if(setting_language == "--DISABLE--")
+ setting_language = null
+ else
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ if(S.speaking != GLOB.all_languages["Noise"]) // check if they are emoting, these do not need to be translated
+ S.speaking = GLOB.all_languages[setting_language]
+
+ return tcm
+
+#undef JOB_STYLE_1
+#undef JOB_STYLE_2
+#undef JOB_STYLE_3
+#undef JOB_STYLE_4
diff --git a/code/game/machinery/tcomms/presets.dm b/code/game/machinery/tcomms/presets.dm
new file mode 100644
index 00000000000..efc98866f62
--- /dev/null
+++ b/code/game/machinery/tcomms/presets.dm
@@ -0,0 +1,32 @@
+/*
+ All machine presets go in here
+*/
+
+// STATION CORE //
+/obj/machinery/tcomms/core/station
+ network_id = "STATION-CORE"
+
+// MINING RELAY //
+/obj/machinery/tcomms/relay/mining
+ network_id = "MINING-RELAY"
+ autolink_id = "STATION-CORE"
+
+// ENGINEERING RELAY //
+/obj/machinery/tcomms/relay/engineering
+ network_id = "ENGINEERING-RELAY"
+ autolink_id = "STATION-CORE"
+ active = FALSE
+
+// RUSKIE RELAY //
+/obj/machinery/tcomms/relay/ruskie
+ network_id = "RUSKIE-RELAY"
+ autolink_id = "STATION-CORE"
+ active = FALSE
+ hidden_link = TRUE
+
+// CC RELAY //
+/obj/machinery/tcomms/relay/cc
+ network_id = "CENTCOMM-RELAY"
+ autolink_id = "STATION-CORE"
+ hidden_link = TRUE
+
diff --git a/code/game/machinery/tcomms/relay.dm b/code/game/machinery/tcomms/relay.dm
new file mode 100644
index 00000000000..b2faf9ce0cd
--- /dev/null
+++ b/code/game/machinery/tcomms/relay.dm
@@ -0,0 +1,170 @@
+/**
+ * # Telecommunications Relay
+ *
+ * Extends the reach of telecomms to the z-level it is built on
+ *
+ * Relays themselves dont do any processing, they just tell the core that this z-level is available in the tcomms network.
+ */
+/obj/machinery/tcomms/relay
+ name = "Telecommunications Relay"
+ desc = "A large device with several radio antennas on it."
+ icon_state = "relay"
+ /// The host core for this relay
+ var/obj/machinery/tcomms/core/linked_core
+ /// ID of the hub to auto link to
+ var/autolink_id
+ /// Is this linked to anything at all
+ var/linked = FALSE
+ /// Is this link invisible on the hub?
+ var/hidden_link = FALSE
+
+/**
+ * Initializer for the relay.
+ *
+ * Calls parent to ensure its added to the GLOB of tcomms machines, before checking if there is an autolink that needs to be added.
+ */
+/obj/machinery/tcomms/relay/Initialize(mapload)
+ . = ..()
+ component_parts += new /obj/item/circuitboard/tcomms/relay(null)
+ if(mapload && autolink_id)
+ return INITIALIZE_HINT_LATELOAD
+
+/**
+ * Descrutor for the relay.
+ *
+ * Ensures that the machine is taken out of the global list when destroyed, and also removes the link to the core.
+ */
+/obj/machinery/tcomms/relay/Destroy()
+ Reset()
+ return ..()
+
+/**
+ * Late Initialize for the relay.
+ *
+ * Calls parent, then adds links to the cores. This is a LateInitialize because the core MUST be initialized first
+ */
+/obj/machinery/tcomms/relay/LateInitialize()
+ . = ..()
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ if(C.network_id == autolink_id)
+ AddLink(C)
+ // Only ONE of these with one ID should exist per world
+ break
+
+/**
+ * Proc to link the relay to the core.
+ *
+ * Sets the linked core to the target (argument below), before adding it to the list of linked relays, then re-freshing the zlevel list
+ * The relay is then marked as linked
+ * Arguments:
+ * * target - The telecomms core that this relay should be linked to
+ */
+/obj/machinery/tcomms/relay/proc/AddLink(obj/machinery/tcomms/core/target)
+ linked_core = target
+ target.linked_relays |= src
+ target.refresh_zlevels()
+ linked = TRUE
+
+/**
+ * Proc to rest the relay.
+ *
+ * Resets the relay, removing its linkage status, and refreshing the core's list of z-levels
+ */
+/obj/machinery/tcomms/relay/proc/Reset()
+ if(linked_core)
+ linked_core.linked_relays -= src
+ linked_core.refresh_zlevels()
+ linked_core = null
+ linked = FALSE
+
+/**
+ * Power Change Handler
+ *
+ * Proc which ensures the host core has its zlevels updated (icons are updated by parent call)
+ */
+/obj/machinery/tcomms/relay/power_change()
+ ..()
+ if(linked_core)
+ linked_core.refresh_zlevels()
+
+//////////////
+// UI STUFF //
+//////////////
+
+/obj/machinery/tcomms/relay/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "tcomms_relay.tmpl", "Telecommunications Relay", 600, 400)
+ ui.open()
+ ui.set_auto_update(1)
+
+/obj/machinery/tcomms/relay/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
+ var/data[0]
+ // Are we on or not
+ data["active"] = active
+ // What is our network ID
+ data["network_id"] = network_id
+ // Are we linked
+ data["linked"] = linked
+ // Is the link hidden
+ data["hidden_link"] = hidden_link
+
+ // Only send linked tab stuff if we are linked. This saves on sending overhead.
+ if(linked)
+ data["linked_core_id"] = linked_core.network_id
+ data["linked_core_addr"] = "\ref[linked_core]"
+
+ else
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ data["entries"] += list(list("addr" = "\ref[C]", "net_id" = C.network_id, "sector" = C.loc.z))
+
+ return data
+
+/obj/machinery/tcomms/relay/Topic(href, href_list)
+ // Check against href exploits
+ if(..())
+ return
+
+ // All the toggle on/offs go here
+ if(href_list["toggle_active"])
+ active = !active
+ update_icon()
+ if(linked_core)
+ linked_core.refresh_zlevels()
+
+ // Set network ID
+ if(href_list["network_id"])
+ var/new_id = input(usr, "Please enter a new network ID", "Network ID", network_id)
+ log_action(usr, "renamed core with ID [network_id] to [new_id]")
+ to_chat(usr, "Device ID changed from [network_id] to [new_id].")
+ network_id = new_id
+
+ if(linked)
+ // Only do these hrefs if we are linked to prevent bugs/exploits
+ if(href_list["toggle_hidden_link"])
+ hidden_link = !hidden_link
+ log_action(usr, "Modified hidden link for [network_id] (Now [hidden_link])")
+
+ if(href_list["unlink"])
+ var/choice = alert(usr, "Are you SURE you want to unlink this relay?\nYou wont be able to re-link without the core password", "Unlink","Yes","No")
+ if(choice == "Yes")
+ log_action(usr, "Unlinked [network_id] from [linked_core.network_id]")
+ Reset()
+ else
+ // You should only be able to link if its not linked, to prevent weirdness
+ if(href_list["link"])
+ var/obj/machinery/tcomms/core/C = locate(href_list["link"])
+ if(istype(C, /obj/machinery/tcomms/core))
+ var/user_pass = input(usr, "Please enter core password","Password Entry")
+ // Check the password
+ if(user_pass == C.link_password)
+ AddLink(C)
+ to_chat(usr, "Successfully linked to [C.network_id].")
+ else
+ to_chat(usr, "ERROR: Password incorrect.")
+ else
+ to_chat(usr, "ERROR: Core not found. Please file an issue report.")
+
+
+ // Hack to speed update the nanoUI
+ SSnanoui.update_uis(src)
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
deleted file mode 100644
index f19bc0fd43b..00000000000
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- The broadcaster sends processed messages to all radio devices in the game. They
- do not have to be headsets; intercoms and station-bounced radios suffice.
-
- They receive their message from a server after the message has been logged.
-*/
-
-GLOBAL_LIST_EMPTY(recentmessages) // global list of recent messages broadcasted : used to circumvent massive radio spam
-GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages list is kept in sync
-
-/obj/machinery/telecomms/broadcaster
- name = "Subspace Broadcaster"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "broadcaster"
- desc = "A dish-shaped machine used to broadcast processed subspace signals."
- density = 1
- anchored = 1
- use_power = IDLE_POWER_USE
- idle_power_usage = 25
- machinetype = 5
- circuitboard = /obj/item/circuitboard/telecomms/broadcaster
-
-/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
- // Don't broadcast rejected signals
- if(signal.data["reject"])
- return
-
- if(signal.data["message"])
-
- // Prevents massive radio spam
- signal.data["done"] = 1 // mark the signal as being broadcasted
- // Search for the original signal and mark it as done as well
- var/datum/signal/original = signal.data["original"]
- if(original)
- original.data["done"] = 1
- original.data["compression"] = signal.data["compression"]
- original.data["level"] = signal.data["level"]
-
- var/signal_message = "[signal.frequency]:[signal.data["message"]]:[signal.data["realname"]]"
- if(signal_message in GLOB.recentmessages)
- return
- GLOB.recentmessages.Add(signal_message)
-
- if(signal.data["slow"] > 0)
- sleep(signal.data["slow"]) // simulate the network lag if necessary
-
- signal.data["level"] |= listening_level
-
- /** #### - Normal Broadcast - #### **/
-
- if(signal.data["type"] == 0)
-
- /* ###### Broadcast a message using signal.data ###### */
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"],,
- signal.data["compression"], signal.data["level"], signal.frequency,
- signal.data["verb"] )
-
-
- /** #### - Simple Broadcast - #### **/
-
- if(signal.data["type"] == 1)
-
- /* ###### Broadcast a message using signal.data ###### */
- Broadcast_SimpleMessage(signal.data["name"], signal.frequency,
- signal.data["message"],null, null,
- signal.data["compression"], listening_level)
-
-
- /** #### - Artificial Broadcast - #### **/
- // (Imitates a mob)
-
- if(signal.data["type"] == 2)
-
- /* ###### Broadcast a message using signal.data ###### */
- // Parameter "data" as 4: AI can't track this person/mob
-
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency,
- signal.data["verb"])
-
- if(!GLOB.message_delay)
- GLOB.message_delay = 1
- spawn(10)
- GLOB.message_delay = 0
- GLOB.recentmessages = list()
-
- /* --- Do a snazzy animation! --- */
- flick("broadcaster_send", src)
-
-/obj/machinery/telecomms/broadcaster/Destroy()
- // In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore.
- if(GLOB.message_delay)
- GLOB.message_delay = 0
- return ..()
-
-
-/*
- Basically just an empty shell for receiving and broadcasting radio messages. Not
- very flexible, but it gets the job done.
-*/
-
-/obj/machinery/telecomms/allinone
- name = "Telecommunications Mainframe"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "comm_server"
- desc = "A compact machine used for portable subspace telecommuniations processing."
- density = 1
- anchored = 1
- use_power = NO_POWER_USE
- idle_power_usage = 0
- machinetype = 6
- var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
-
-/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal)
-
- if(!on) // has to be on to receive messages
- return
-
- if(is_freq_listening(signal)) // detect subspace signals
-
- signal.data["done"] = 1 // mark the signal as being broadcasted
- signal.data["compression"] = 0
-
- // Search for the original signal and mark it as done as well
- var/datum/signal/original = signal.data["original"]
- if(original)
- original.data["done"] = 1
-
- if(signal.data["slow"] > 0)
- sleep(signal.data["slow"]) // simulate the network lag if necessary
-
- /* ###### Broadcast a message using signal.data ###### */
-
- var/datum/radio_frequency/connection = signal.data["connection"]
-
- if(connection.frequency in SSradio.ANTAG_FREQS) // if antag broadcast, just
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency,
- signal.data["verb"])
- else
- if(intercept)
- Broadcast_Message(signal.data["connection"], signal.data["mob"],
- signal.data["vmask"], signal.data["vmessage"],
- signal.data["radio"], signal.data["message"],
- signal.data["name"], signal.data["job"],
- signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency,
- signal.data["verb"])
-
-#define CREW_RADIO_TYPE 0
-#define CENTCOMM_RADIO_TYPE 1
-#define SYNDICATE_RADIO_TYPE 2
-/proc/Is_Bad_Connection(old_freq, new_freq) //Makes sure players cant read radios of a higher level than they are
- var/old_type = CREW_RADIO_TYPE
- var/new_type = CREW_RADIO_TYPE
- for(var/antag_freq in SSradio.ANTAG_FREQS)
- if(old_freq == antag_freq)
- old_type = SYNDICATE_RADIO_TYPE
- if(new_freq == antag_freq)
- new_type = SYNDICATE_RADIO_TYPE
-
- for(var/cent_freq in SSradio.CENT_FREQS)
- if(old_freq == cent_freq)
- old_type = CENTCOMM_RADIO_TYPE
- if(new_freq == cent_freq)
- new_type = CENTCOMM_RADIO_TYPE
-
- return new_type > old_type
-
-/**
-
- Here is the big, bad function that broadcasts a message given the appropriate
- parameters.
-
- @param connection:
- The datum generated in radio.dm, stored in signal.data["connection"].
-
- @param M:
- Reference to the mob/speaker, stored in signal.data["mob"]
-
- @param vmask:
- Boolean value if the mob is "hiding" its identity via voice mask, stored in
- signal.data["vmask"]
-
- @param vmessage:
- If specified, will display this as the message; such as "chimpering"
- for monkies if the mob is not understood. Stored in signal.data["vmessage"].
-
- @param radio:
- Reference to the radio broadcasting the message, stored in signal.data["radio"]
-
- @param message:
- The actual string message to display to mobs who understood mob M. Stored in
- signal.data["message"]
-
- @param name:
- The name to display when a mob receives the message. signal.data["name"]
-
- @param job:
- The name job to display for the AI when it receives the message. signal.data["job"]
-
- @param realname:
- The "real" name associated with the mob. signal.data["realname"]
-
- @param vname:
- If specified, will use this name when mob M is not understood. signal.data["vname"]
-
- @param data:
- If specified:
- 1 -- Will only broadcast to intercoms
- 2 -- Will only broadcast to intercoms and station-bounced radios
- 3 -- Broadcast to syndicate frequency
- 4 -- AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob
-
- @param compression:
- If 0, the signal is audible
- If nonzero, the signal may be partially inaudible or just complete gibberish.
-
- @param level:
- The list of Z levels that the sending radio is broadcasting to. Having 0 in the list broadcasts on all levels
-
- @param freq
- The frequency of the signal
-
-**/
-
-/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
- var/vmask, list/vmessage_pieces, var/obj/item/radio/radio,
- list/message_pieces, var/name, var/job, var/realname, var/vname,
- var/data, var/compression, var/list/level, var/freq, var/verbage = "says",
- var/atom/follow_target = null)
-
-
- /* ###### Prepare the radio connection ###### */
-
- var/display_freq = freq
-
- var/bad_connection = FALSE
- var/datum/radio_frequency/new_connection = connection
-
- if(connection.frequency != display_freq)
- bad_connection = Is_Bad_Connection(connection.frequency, display_freq)
- new_connection = SSradio.return_frequency(display_freq)
-
- var/list/obj/item/radio/radios = list()
-
- // --- Broadcast only to intercom devices ---
-
- if(data == 1 && !bad_connection)
-
- for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"])
- if(R.receive_range(display_freq, level) > -1)
- radios += R
-
- // --- Broadcast only to intercoms and station-bounced radios ---
-
- else if(data == 2 && !bad_connection)
-
- for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"])
-
- if(istype(R, /obj/item/radio/headset))
- continue
-
- if(R.receive_range(display_freq, level) > -1)
- radios += R
-
- // --- Broadcast to antag radios! ---
-
- else if(data == 3)
- for(var/antag_freq in SSradio.ANTAG_FREQS)
- var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq)
- for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"])
- if(R.receive_range(antag_freq, level) > -1)
- radios += R
-
- // --- Broadcast to ALL radio devices ---
-
- else if(!bad_connection)
-
- for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"])
- if(R.receive_range(display_freq, level) > -1)
- radios += R
-
- // Get a list of mobs who can hear from the radios we collected.
- var/list/receive = get_mobs_in_radio_ranges(radios)
-
- /* ###### Organize the receivers into categories for displaying the message ###### */
-
- // Understood the message:
- var/list/heard_masked = list() // masked name or no real name
- var/list/heard_normal = list() // normal message
-
- // Did not understand the message:
- var/list/heard_voice = list() // voice message (ie "chimpers")
- var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
- var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
-
- for(var/mob/R in receive)
-
- /* --- Loop through the receivers and categorize them --- */
-
- if(is_admin(R) && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
-
- if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
- continue
-
- // Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates
- if(data == 3 && istype(R, /mob/dead/observer) && R.get_preference(CHAT_GHOSTRADIO))
- continue
-
- // --- Check for compression ---
- if(compression > 0)
- heard_gibberish += R
- continue
-
- // --- Can understand the speech ---
-
- if(!M || R.say_understands(M))
-
- // - Not human or wearing a voice mask -
- if(!M || !ishuman(M) || vmask)
- heard_masked += R
-
- // - Human and not wearing voice mask -
- else
- heard_normal += R
-
- // --- Can't understand the speech ---
-
- else
- // - The speaker has a prespecified "voice message" to display if not understood -
- if(vmessage_pieces)
- heard_voice += R
-
- // - Just display a garbled message -
- else
- heard_garbled += R
-
-
- /* ###### Begin formatting and sending the message ###### */
- if(length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
-
- /* --- Some miscellaneous variables to format the string output --- */
- var/freq_text = get_frequency_name(display_freq)
-
- var/part_b_extra = ""
- if(data == 3) // intercepted radio message
- part_b_extra = " (Intercepted)"
- var/part_a = "\[[freq_text]\][part_b_extra]" // goes in the actual output
-
- // --- Some more pre-message formatting ---
- var/part_b = "" // Tweaked for security headsets -- TLE
- var/part_c = ""
-
-
- // --- Filter the message; place it in quotes apply a verb ---
- var/quotedmsg = null
- if(M)
- quotedmsg = "[M.say_quote(multilingual_to_message(message_pieces))], \"[multilingual_to_message(message_pieces)]\""
- else
- quotedmsg = "says, \"[multilingual_to_message(message_pieces)]\""
-
- // --- This following recording is intended for research and feedback in the use of department radio channels ---
-
- var/part_blackbox_b = " \[[freq_text]\]" // Tweaked for security headsets -- TLE
- var/blackbox_msg = "[part_a][name][part_blackbox_b][quotedmsg][part_c]"
- //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
-
- //BR.messages_admin += blackbox_admin_msg
- if(istype(GLOB.blackbox))
- switch(display_freq)
- if(PUB_FREQ)
- GLOB.blackbox.msg_common += blackbox_msg
- if(SCI_FREQ)
- GLOB.blackbox.msg_science += blackbox_msg
- if(COMM_FREQ)
- GLOB.blackbox.msg_command += blackbox_msg
- if(MED_FREQ)
- GLOB.blackbox.msg_medical += blackbox_msg
- if(ENG_FREQ)
- GLOB.blackbox.msg_engineering += blackbox_msg
- if(SEC_FREQ)
- GLOB.blackbox.msg_security += blackbox_msg
- if(DTH_FREQ)
- GLOB.blackbox.msg_deathsquad += blackbox_msg
- if(SYND_FREQ)
- GLOB.blackbox.msg_syndicate += blackbox_msg
- if(SYNDTEAM_FREQ)
- GLOB.blackbox.msg_syndteam += blackbox_msg
- if(SUP_FREQ)
- GLOB.blackbox.msg_cargo += blackbox_msg
- if(SRV_FREQ)
- GLOB.blackbox.msg_service += blackbox_msg
- else
- GLOB.blackbox.messages += blackbox_msg
-
- //End of research and feedback code.
-
- /* ###### Send the message ###### */
-
-
- /* --- Process all the mobs that heard a masked voice (understood) --- */
-
- if(length(heard_masked))
- for(var/mob/R in heard_masked)
- R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, name, follow_target=follow_target)
-
- /* --- Process all the mobs that heard the voice normally (understood) --- */
-
- if(length(heard_normal))
- for(var/mob/R in heard_normal)
- R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, realname, follow_target=follow_target)
-
- /* --- Process all the mobs that heard the voice normally (did not understand) --- */
-
- if(length(heard_voice))
- for(var/mob/R in heard_voice)
- R.hear_radio(message_pieces, verbage, part_a, part_b, M,0, vname, follow_target=follow_target)
-
- /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
- // Displays garbled message (ie "f*c* **u, **i*er!")
-
- if(length(heard_garbled))
- for(var/mob/R in heard_garbled)
- R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, vname, follow_target=follow_target)
-
-
- /* --- Complete gibberish. Usually happens when there's a compressed message --- */
-
- if(length(heard_gibberish))
- for(var/mob/R in heard_gibberish)
- R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, follow_target=follow_target)
-
- return 1
-
-/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level)
- var/text = multilingual_to_message(message_pieces)
- /* ###### Prepare the radio connection ###### */
-
- var/mob/living/carbon/human/H
- if(!M)
- H = new
- M = H
-
- var/datum/radio_frequency/connection = SSradio.return_frequency(frequency)
-
- var/display_freq = connection.frequency
-
- var/list/receive = list()
-
-
- // --- Broadcast only to intercom devices ---
-
- if(data == 1)
- for(var/obj/item/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
- var/turf/position = get_turf(R)
- // TODO: Make the radio system cooperate with the space manager
- if(position && position.z == level)
- receive |= R.send_hear(display_freq, level)
-
-
- // --- Broadcast only to intercoms and station-bounced radios ---
-
- else if(data == 2)
- for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"])
-
- if(istype(R, /obj/item/radio/headset))
- continue
- var/turf/position = get_turf(R)
- // TODO: Make the radio system cooperate with the space manager
- if(position && position.z == level)
- receive |= R.send_hear(display_freq)
-
-
- // --- Broadcast to antag radios! ---
-
- else if(data == 3)
- for(var/freq in SSradio.ANTAG_FREQS)
- var/datum/radio_frequency/antag_connection = SSradio.return_frequency(freq)
- for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"])
- var/turf/position = get_turf(R)
- // TODO: Make the radio system cooperate with the space manager
- if(position && position.z == level)
- receive |= R.send_hear(freq)
-
-
- // --- Broadcast to ALL radio devices ---
-
- else
- for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"])
- var/turf/position = get_turf(R)
- // TODO: Make the radio system cooperate with the space manager
- if(position && position.z == level)
- receive |= R.send_hear(display_freq)
-
-
- /* ###### Organize the receivers into categories for displaying the message ###### */
-
- // Understood the message:
- var/list/heard_normal = list() // normal message
-
- // Did not understand the message:
- var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
- var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
-
- for(var/mob/R in receive)
-
- /* --- Loop through the receivers and categorize them --- */
-
- if(R.client && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
-
-
- // --- Check for compression ---
- if(compression > 0)
-
- heard_gibberish += R
- continue
-
- // --- Can understand the speech ---
-
- if(R.say_understands(M))
-
- heard_normal += R
-
- // --- Can't understand the speech ---
-
- else
- // - Just display a garbled message -
-
- heard_garbled += R
-
-
- /* ###### Begin formatting and sending the message ###### */
- if(length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
-
- /* --- Some miscellaneous variables to format the string output --- */
- var/part_a = "" // goes in the actual output
- var/freq_text = get_frequency_name(display_freq)
-
- // --- Some more pre-message formatting ---
-
- var/part_b_extra = ""
- if(data == 3) // intercepted radio message
- part_b_extra = " (Intercepted)"
-
- var/part_b = " \[[freq_text]\][part_b_extra]" // Tweaked for security headsets -- TLE
- var/part_blackbox_b = " \[[freq_text]\]"
- var/part_c = ""
-
- var/blackbox_msg = "[part_a][source][part_blackbox_b]\"[text]\"[part_c]"
-
- //BR.messages_admin += blackbox_admin_msg
- if(istype(GLOB.blackbox))
- switch(display_freq)
- if(PUB_FREQ)
- GLOB.blackbox.msg_common += blackbox_msg
- if(SCI_FREQ)
- GLOB.blackbox.msg_science += blackbox_msg
- if(COMM_FREQ)
- GLOB.blackbox.msg_command += blackbox_msg
- if(MED_FREQ)
- GLOB.blackbox.msg_medical += blackbox_msg
- if(ENG_FREQ)
- GLOB.blackbox.msg_engineering += blackbox_msg
- if(SEC_FREQ)
- GLOB.blackbox.msg_security += blackbox_msg
- if(DTH_FREQ)
- GLOB.blackbox.msg_deathsquad += blackbox_msg
- if(SYND_FREQ)
- GLOB.blackbox.msg_syndicate += blackbox_msg
- if(SYNDTEAM_FREQ)
- GLOB.blackbox.msg_syndteam += blackbox_msg
- if(SUP_FREQ)
- GLOB.blackbox.msg_cargo += blackbox_msg
- if(SRV_FREQ)
- GLOB.blackbox.msg_service += blackbox_msg
- else
- GLOB.blackbox.messages += blackbox_msg
-
- //End of research and feedback code.
-
- /* ###### Send the message ###### */
-
- /* --- Process all the mobs that heard the voice normally (understood) --- */
-
- if(length(heard_normal))
- var/rendered = "[part_a][source][part_b]\"[text]\"[part_c]"
-
- for(var/mob/R in heard_normal)
- R.show_message(rendered, 2)
-
- /* --- Process all the mobs that heard a garbled voice (did not understand) --- */
- // Displays garbled message (ie "f*c* **u, **i*er!")
-
- if(length(heard_garbled))
- var/quotedmsg = "\"[stars(text)]\""
- var/rendered = "[part_a][source][part_b][quotedmsg][part_c]"
-
- for(var/mob/R in heard_garbled)
- R.show_message(rendered, 2)
-
-
- /* --- Complete gibberish. Usually happens when there's a compressed message --- */
-
- if(length(heard_gibberish))
- var/quotedmsg = "\"[Gibberish(text, compression + 50)]\""
- var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]"
-
- for(var/mob/R in heard_gibberish)
- R.show_message(rendered, 2)
-
- if(H)
- qdel(H)
-
-//Use this to test if an obj can communicate with a Telecommunications Network
-
-/atom/proc/test_telecomms()
- var/datum/signal/signal = src.telecomms_process()
- var/turf/position = get_turf(src)
- // TODO: Make the radio system cooperate with the space manager
- return (position.z in signal.data["level"]) && signal.data["done"]
-
-/atom/proc/telecomms_process(var/do_sleep = 1)
-
- // First, we want to generate a new radio signal
- var/datum/signal/signal = new
- signal.transmission_method = 2 // 2 would be a subspace transmission.
- var/turf/pos = get_turf(src)
-
- // --- Finally, tag the actual signal with the appropriate values ---
- signal.data = list(
- "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
- "message" = "TEST",
- "compression" = rand(45, 50), // If the signal is compressed, compress our message too.
- "traffic" = 0, // dictates the total traffic sum that the signal went through
- "type" = 4, // determines what type of radio input it is: test broadcast
- "reject" = 0,
- "done" = 0,
- // TODO: Make the radio system cooperate with the space manager
- "level" = pos.z // The level it is being broadcasted at.
- )
- signal.frequency = PUB_FREQ// Common channel
-
- //#### Sending the signal to all subspace receivers ####//
- for(var/obj/machinery/telecomms/receiver/R in GLOB.telecomms_list)
- spawn(0)
- R.receive_signal(signal)
-
- if(do_sleep)
- sleep(rand(10,25))
-
- //log_world("Level: [signal.data["level"]] - Done: [signal.data["done"]]")
-
- return signal
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
deleted file mode 100644
index f0b5a945f92..00000000000
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ /dev/null
@@ -1,219 +0,0 @@
-/obj/machinery/computer/telecomms
-
- light_color = LIGHT_COLOR_DARKGREEN
-
-/obj/machinery/computer/telecomms/server
- name = "telecommunications server monitor"
- icon_screen = "comm_logs"
-
-
- var/screen = 0 // the screen number:
- var/list/servers = list() // the servers located by the computer
- var/obj/machinery/telecomms/server/SelectedServer
-
- var/network = "NULL" // the network to probe
- var/temp = "" // temporary feedback messages
-
- var/universal_translate = 0 // set to 1 if it can translate nonhuman speech
-
- req_access = list(ACCESS_TCOMSAT)
- circuit = /obj/item/circuitboard/comm_server
-
- attack_hand(mob/user as mob)
- if(stat & (BROKEN|NOPOWER))
- return
- user.set_machine(src)
- var/list/dat = list()
- dat += "Telecommunication Server Monitor
Telecommunications Server Monitor
"
-
- switch(screen)
-
-
- // --- Main Menu ---
-
- if(0)
- dat += " [temp] "
- dat += " Current Network: [network] "
- if(servers.len)
- dat += " Detected Telecommunication Servers:
"
- for(var/obj/machinery/telecomms/T in servers)
- dat += "
"
- dat += " Current Network: [network]"
- dat += " Selected Server: [SelectedServer.id]"
-
- if(SelectedServer.totaltraffic >= 1024)
- dat += " Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes
"
- else
- dat += " Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes
"
-
- dat += "Stored Logs: "
-
- var/i = 0
- for(var/datum/comm_log_entry/C in SelectedServer.log_entries)
- i++
- // If the log is a speech file
- if(C.input_type == "Speech File")
- dat += "
[C.name] \[X\] "
-
- // -- If the orator is a human, or universal translate is active, OR mob has universal speech on --
-
- if(user.say_understands(null, C.parameters["language"]) || universal_translate || C.parameters["uspeech"])
- dat += "Data type: [C.input_type] "
- dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]]) "
- dat += "Class: [C.parameters["race"]] "
- dat += "Contents: \"[C.parameters["message"]]\" "
-
-
- // -- Orator is not human and universal translate not active --
-
- else
- dat += "Data type: Audio File "
- dat += "Source: Unidentifiable "
- dat += "Class: [C.parameters["race"]] "
- dat += "Contents: Unintelligble "
-
- dat += "
"
- dat += ""
-
-
-
- user << browse(dat, "window=comm_monitor;size=575x400")
- onclose(user, "server_control")
-
- temp = ""
- return
-
-
- Topic(href, href_list)
- if(..())
- return
-
-
- add_fingerprint(usr)
- usr.set_machine(src)
-
- if(href_list["viewmachine"])
- screen = 1
- for(var/obj/machinery/telecomms/T in machinelist)
- if(T.id == href_list["viewmachine"])
- SelectedMachine = T
- break
-
- if(href_list["operation"])
- switch(href_list["operation"])
-
- if("release")
- machinelist = list()
- screen = 0
-
- if("mainmenu")
- screen = 0
-
- if("probe")
- if(machinelist.len > 0)
- temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -"
-
- else
- for(var/obj/machinery/telecomms/T in range(25, src))
- if(T.network == network)
- machinelist.Add(T)
-
- if(!machinelist.len)
- temp = "- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -"
- else
- temp = "- [machinelist.len] ENTITIES LOCATED & BUFFERED -"
-
- screen = 0
-
-
- if(href_list["network"])
-
- var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text
- if(newnet && ((usr in range(1, src) || issilicon(usr))))
- if(length(newnet) > 15)
- temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -"
-
- else
- network = newnet
- screen = 0
- machinelist = list()
- temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -"
-
- updateUsrDialog()
- return
-
- attackby(var/obj/item/D as obj, var/mob/user as mob, params)
- if(istype(D, /obj/item/screwdriver))
- playsound(src.loc, D.usesound, 50, 1)
- if(do_after(user, 20 * D.toolspeed, target = src))
- if(src.stat & BROKEN)
- to_chat(user, "The broken glass falls out.")
- var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
- new /obj/item/shard(loc)
- var/obj/item/circuitboard/comm_monitor/M = new /obj/item/circuitboard/comm_monitor( A )
- for(var/obj/C in src)
- C.loc = src.loc
- A.circuit = M
- A.state = 3
- A.icon_state = "3"
- A.anchored = 1
- qdel(src)
- else
- to_chat(user, "You disconnect the monitor.")
- var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
- var/obj/item/circuitboard/comm_monitor/M = new /obj/item/circuitboard/comm_monitor( A )
- for(var/obj/C in src)
- C.loc = src.loc
- A.circuit = M
- A.state = 4
- A.icon_state = "4"
- A.anchored = 1
- qdel(src)
- updateUsrDialog()
- return
- return ..()
-
- emag_act(user as mob)
- if(!emagged)
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
- emagged = 1
- to_chat(user, "You you disable the security protocols")
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
deleted file mode 100644
index 55997d49105..00000000000
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ /dev/null
@@ -1,49 +0,0 @@
-/obj/machinery/computer/telecomms/traffic
- name = "telecommunications traffic control"
-
- light_color = LIGHT_COLOR_DARKGREEN
-
- req_access = list(ACCESS_TCOMSAT)
- circuit = /obj/item/circuitboard/comm_traffic
-
- // NTTC
- var/window_id // mostly used to let the configuration datum update the user's UI
- var/unlocked = FALSE
-
-/obj/machinery/computer/telecomms/traffic/multitool_act(mob/user, obj/item/I)
- . = TRUE
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
- return
- unlocked = !unlocked
- to_chat(user, "This computer is now [unlocked ? "Unlocked" : "Locked"]. Reopen the UI to see the difference.")
-
-/obj/machinery/computer/telecomms/traffic/attack_hand(mob/user)
- interact(user)
-
-/obj/machinery/computer/telecomms/traffic/interact(mob/user)
- if(stat & (BROKEN|NOPOWER))
- return 0
-
- if(GLOB.nttc_config.valid_languages.len == 1)
- GLOB.nttc_config.update_languages() // this is silly but it has to be done because NTTC inits before languages do
-
- var/datum/asset/assets = get_asset_datum(/datum/asset/simple/nttc)
- assets.send(user)
-
- var/dat = file2text("html/nttc/dist/index.html")
- if(unlocked)
- dat += "\n"
- var/datum/browser/nttc/nt_browser = new(user, name, "NTTC", 720, 480, src, GLOB.nttc_config.nttc_serialize())
- nt_browser.set_content(dat)
- nt_browser.open()
- window_id = nt_browser.window_id
-
-/obj/machinery/computer/telecomms/traffic/Topic(href, href_list)
- if(..())
- return 1
-
- var/mob/user = usr
- if(!istype(user) || !user.client)
- return 0
-
- GLOB.nttc_config.Topic(user, href_list, window_id, src)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index b92e3c78bb8..59bae3174c4 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -79,7 +79,7 @@
/obj/machinery/computer/teleporter/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
var/data[0]
data["powerstation"] = power_station
- if(power_station)
+ if(power_station?.teleporter_hub)
data["teleporterhub"] = power_station.teleporter_hub
data["calibrated"] = power_station.teleporter_hub.calibrated
data["accurate"] = power_station.teleporter_hub.accurate
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index c0b1c44f806..cc9fc3e4666 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -317,7 +317,7 @@
scramble(1, H, 100)
H.generate_name()
H.sync_organ_dna(assimilate = 1)
- H.update_body(0)
+ H.update_body()
H.reset_hair()
H.dna.ResetUIFrom(H)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index e3b1322f34b..7aa5661febe 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -52,14 +52,11 @@
var/list/hidden_records = list()
var/list/coin_records = list()
- // // Variables used to initialize advertising
- var/product_slogans = "" //String of slogans separated by semicolons, optional
- var/product_ads = "" //String of small ad messages in the vending screen - random chance
- var/list/ads_list = list()
+ var/list/ads_list = list() //Small ad messages in the vending screen - random chance, TODO: implementation
// Stuff relating vocalizations
- var/list/slogan_list = list()
+ var/list/slogan_list = list() //List of slogans the vendor will say, optional
var/vend_reply //Thank you for shopping!
var/shut_up = 0 //Stop spouting those godawful pitches!
///can we access the hidden inventory?
@@ -95,17 +92,12 @@
build_inventory(products, product_records)
build_inventory(contraband, hidden_records)
build_inventory(premium, coin_records)
- if(product_slogans)
- slogan_list += splittext(product_slogans, ";")
-
+ if(LAZYLEN(slogan_list))
// So not all machines speak at the exact same time.
// The first time this machine says something will be at slogantime + this random value,
- // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
+ // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is created.
last_slogan = world.time + rand(0, slogan_delay)
- if(product_ads)
- ads_list += splittext(product_ads, ";")
-
power_change()
/obj/machinery/vending/Destroy()
@@ -198,7 +190,6 @@
var/obj/item/vending_refill/R = locate() in component_parts
if(!R)
CRASH("Constructible vending machine did not have a refill canister")
- return
R.products = unbuild_inventory(product_records)
R.contraband = unbuild_inventory(hidden_records)
@@ -720,7 +711,7 @@
src.seconds_electrified--
//Pitch to the people! Really sell it!
- if(((last_slogan + src.slogan_delay) <= world.time) && (slogan_list.len > 0) && (!shut_up) && prob(5))
+ if(((last_slogan + src.slogan_delay) <= world.time) && (LAZYLEN(slogan_list)) && (!shut_up) && prob(5))
var/slogan = pick(src.slogan_list)
speak(slogan)
last_slogan = world.time
@@ -833,7 +824,7 @@
products = list( /obj/item/assembly/prox_sensor = 5,/obj/item/assembly/igniter = 3,/obj/item/assembly/signaler = 4,
/obj/item/wirecutters = 1, /obj/item/cartridge/signal = 4)
contraband = list(/obj/item/flashlight = 5,/obj/item/assembly/timer = 2, /obj/item/assembly/voice = 2, /obj/item/assembly/health = 2)
- product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
+ ads_list = list("Only the finest!","Have some tools.","The most robust equipment.","The finest gear in space!")
refill_canister = /obj/item/vending_refill/assist
/obj/machinery/vending/assist/Initialize(mapload)
@@ -875,8 +866,8 @@
/obj/item/reagent_containers/food/drinks/ice = 9)
contraband = list(/obj/item/reagent_containers/food/drinks/tea = 10)
vend_delay = 15
- product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?"
- product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
+ slogan_list = list("I hope nobody asks me for a bloody cup o' tea...","Alcohol is humanity's friend. Would you abandon a friend?","Quite delighted to serve you!","Is nobody thirsty on this station?")
+ ads_list = list("Drink up!","Booze is good for you!","Alcohol is humanity's best friend.","Quite delighted to serve you!","Care for a nice, cold beer?","Nothing cures you like booze!","Have a sip!","Have a drink!","Have a beer!","Beer is good for you!","Only the finest alcohol!","Best quality booze since 2053!","Award-winning wine!","Maximum alcohol!","Man loves beer.","A toast for progress!")
refill_canister = /obj/item/vending_refill/boozeomat
/obj/machinery/vending/boozeomat/syndicate_access
@@ -895,7 +886,7 @@
/obj/machinery/vending/coffee
name = "\improper Hot Drinks machine"
desc = "A vending machine which dispenses hot drinks."
- product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
+ ads_list = list("Have a drink!","Drink up!","It's good for you!","Would you like a hot joe?","I'd kill for some coffee!","The best beans in the galaxy.","Only the finest brew for you.","Mmmm. Nothing like a coffee.","I like coffee, don't you?","Coffee helps you work!","Try some tea.","We hope you like the best!","Try our new chocolate!","Admin conspiracies")
icon_state = "coffee"
icon_vend = "coffee-vend"
item_slot = TRUE
@@ -962,8 +953,8 @@
/obj/machinery/vending/snack
name = "\improper Getmore Chocolate Corp"
desc = "A snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars."
- product_slogans = "Try our new nougat bar!;Twice the calories for half the price!"
- product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!"
+ slogan_list = list("Try our new nougat bar!","Twice the calories for half the price!")
+ ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!")
icon_state = "snack"
products = list(/obj/item/reagent_containers/food/snacks/candy/candybar = 6,/obj/item/reagent_containers/food/drinks/dry_ramen = 6,/obj/item/reagent_containers/food/snacks/chips =6,
/obj/item/reagent_containers/food/snacks/sosjerky = 6,/obj/item/reagent_containers/food/snacks/no_raisin = 6,/obj/item/reagent_containers/food/snacks/pistachios =6,
@@ -989,7 +980,7 @@
/obj/machinery/vending/chinese
name = "\improper Mr. Chang"
desc = "A self-serving Chinese food machine, for all your Chinese food needs."
- product_slogans = "Taste 5000 years of culture!;Mr. Chang, approved for safe consumption in over 10 sectors!;Chinese food is great for a date night, or a lonely night!;You can't go wrong with Mr. Chang's authentic Chinese food!"
+ slogan_list = list("Taste 5000 years of culture!","Mr. Chang, approved for safe consumption in over 10 sectors!","Chinese food is great for a date night, or a lonely night!","You can't go wrong with Mr. Chang's authentic Chinese food!")
icon_state = "chang"
products = list(/obj/item/reagent_containers/food/snacks/chinese/chowmein = 6, /obj/item/reagent_containers/food/snacks/chinese/tao = 6, /obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball = 6, /obj/item/reagent_containers/food/snacks/chinese/newdles = 6,
/obj/item/reagent_containers/food/snacks/chinese/rice = 6)
@@ -1013,8 +1004,8 @@
name = "\improper Robust Softdrinks"
desc = "A soft drink vendor provided by Robust Industries, LLC."
icon_state = "Cola_Machine"
- product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!"
- product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space."
+ slogan_list = list("Robust Softdrinks: More robust than a toolbox to the head!")
+ ads_list = list("Refreshing!","Hope you're thirsty!","Over 1 million drinks sold!","Thirsty? Why not cola?","Please, have a drink!","Drink up!","The best drinks in space.")
products = list(/obj/item/reagent_containers/food/drinks/cans/cola = 10,/obj/item/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/reagent_containers/food/drinks/cans/starkist = 10,
/obj/item/reagent_containers/food/drinks/cans/space_up = 10,/obj/item/reagent_containers/food/drinks/cans/grape_juice = 10)
@@ -1040,7 +1031,7 @@
/obj/machinery/vending/cart
name = "\improper PTech"
desc = "Cartridges for PDA's."
- product_slogans = "Carts to go!"
+ slogan_list = list("Carts to go!")
icon_state = "cart"
icon_deny = "cart-deny"
products = list(/obj/item/pda =10,/obj/item/cartridge/mob_hunt_game = 25,/obj/item/cartridge/medical = 10,/obj/item/cartridge/chemistry = 10,
@@ -1069,8 +1060,8 @@
desc = "An overwhelming amount of ancient patriotism washes over you just by looking at the machine."
icon_state = "liberationstation"
req_access_txt = "1"
- product_slogans = "Liberation Station: Your one-stop shop for all things second amendment!;Be a patriot today, pick up a gun!;Quality weapons for cheap prices!;Better dead than red!"
- product_ads = "Float like an astronaut, sting like a bullet!;Express your second amendment today!;Guns don't kill people, but you can!;Who needs responsibilities when you have guns?"
+ slogan_list = list("Liberation Station: Your one-stop shop for all things second amendment!","Be a patriot today, pick up a gun!","Quality weapons for cheap prices!","Better dead than red!")
+ ads_list = list("Float like an astronaut, sting like a bullet!","Express your second amendment today!","Guns don't kill people, but you can!","Who needs responsibilities when you have guns?")
vend_reply = "Remember the name: Liberation Station!"
products = list(/obj/item/gun/projectile/automatic/pistol/deagle/gold = 2,/obj/item/gun/projectile/automatic/pistol/deagle/camo = 2,
/obj/item/gun/projectile/automatic/pistol/m1911 = 2,/obj/item/gun/projectile/automatic/proto = 2,
@@ -1086,8 +1077,8 @@
name = "\improper Syndicate Donksoft Toy Vendor"
desc = "An ages 8 and up approved vendor that dispenses toys. If you were to find the right wires, you can unlock the adult mode setting!"
icon_state = "syndi"
- product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get permabrigged!"
- product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!"
+ slogan_list = list("Get your cool toys today!","Trigger a valid hunter today!","Quality toy weapons for cheap prices!","Give them to HoPs for all access!","Give them to HoS to get permabrigged!")
+ ads_list = list("Feel robust with your toys!","Express your inner child today!","Toy weapons don't kill people, but valid hunters do!","Who needs responsibilities when you have toy weapons?","Make your next murder FUN!")
vend_reply = "Come back for more!"
products = list(/obj/item/gun/projectile/automatic/toy = 10,
/obj/item/gun/projectile/automatic/toy/pistol= 10,
@@ -1112,8 +1103,8 @@
/obj/machinery/vending/cigarette
name = "cigarette machine"
desc = "If you want to get cancer, might as well do it in style."
- product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
- product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs."
+ slogan_list = list("Space cigs taste good like a cigarette should.","I'd rather toolbox than switch.","Smoke!","Don't believe the reports - smoke today!")
+ ads_list = list("Probably not bad for you!","Don't believe the scientists!","It's good for you!","Don't quit, buy more!","Smoke!","Nicotine heaven.","Best cigarettes since 2150.","Award-winning cigs.")
vend_delay = 34
icon_state = "cigs"
products = list(/obj/item/storage/fancy/cigarettes/cigpack_robust = 12, /obj/item/storage/fancy/cigarettes/cigpack_uplift = 6, /obj/item/storage/fancy/cigarettes/cigpack_random = 6, /obj/item/reagent_containers/food/pill/patch/nicotine = 10, /obj/item/storage/box/matches = 10,/obj/item/lighter/random = 4,/obj/item/storage/fancy/rollingpapers = 5)
@@ -1141,8 +1132,8 @@
/obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin
name = "\improper ShadyCigs Ultra"
desc = "Now with extra premium products!"
- product_ads = "Probably not bad for you!;Dope will get you through times of no money better than money will get you through times of no dope!;It's good for you!"
- product_slogans = "Turn on, tune in, drop out!;Better living through chemistry!;Toke!;Don't forget to keep a smile on your lips and a song in your heart!"
+ ads_list = list("Probably not bad for you!","Dope will get you through times of no money better than money will get you through times of no dope!","It's good for you!")
+ slogan_list = list("Turn on, tune in, drop out!","Better living through chemistry!","Toke!","Don't forget to keep a smile on your lips and a song in your heart!")
products = list(/obj/item/storage/fancy/cigarettes = 5,
/obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
/obj/item/storage/fancy/cigarettes/cigpack_robust = 3,
@@ -1170,9 +1161,9 @@
desc = "Medical drug dispenser."
icon_state = "med"
icon_deny = "med-deny"
- product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
+ ads_list = list("Go save some lives!","The best stuff for your medbay.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?","Ping!")
req_access_txt = "5"
- products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/food/pill/patch/styptic = 10, /obj/item/reagent_containers/food/pill/patch/silver_sulf = 10,
+ products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/food/pill/patch/styptic = 4, /obj/item/reagent_containers/food/pill/patch/silver_sulf = 4, /obj/item/reagent_containers/applicator/brute = 3, /obj/item/reagent_containers/applicator/burn = 3,
/obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/diphenhydramine = 4,
/obj/item/reagent_containers/glass/bottle/salicylic = 4, /obj/item/reagent_containers/glass/bottle/potassium_iodide =3, /obj/item/reagent_containers/glass/bottle/saline = 5,
/obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/ether = 4, /obj/item/reagent_containers/glass/bottle/atropine = 3,
@@ -1209,7 +1200,7 @@
/obj/machinery/vending/wallmed
name = "\improper NanoMed"
desc = "Wall-mounted Medical Equipment dispenser."
- product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
+ ads_list = list("Go save some lives!","The best stuff for your medbay.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?")
icon_state = "wallmed"
icon_deny = "wallmed-deny"
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
@@ -1233,7 +1224,7 @@
desc = "EVIL wall-mounted Medical Equipment dispenser."
icon_state = "syndimed"
icon_deny = "syndimed-deny"
- product_ads = "Go end some lives!;The best stuff for your ship.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
+ ads_list = list("Go end some lives!","The best stuff for your ship.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?","Ping!")
req_access_txt = "150"
products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/reagent_containers/hypospray/autoinjector = 4,/obj/item/healthanalyzer = 1)
contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4,/obj/item/reagent_containers/syringe/antiviral = 4,/obj/item/reagent_containers/food/pill/tox = 1)
@@ -1241,7 +1232,7 @@
/obj/machinery/vending/security
name = "\improper SecTech"
desc = "A security equipment vendor."
- product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?"
+ ads_list = list("Crack capitalist skulls!","Beat some heads in!","Don't forget - harm is good!","Your weapons are right here.","Handcuffs!","Freeze, scumbag!","Don't tase me bro!","Tase them, bro.","Why not have a donut?")
icon_state = "sec"
icon_deny = "sec-deny"
req_access_txt = "1"
@@ -1263,8 +1254,8 @@
/obj/machinery/vending/hydronutrients
name = "\improper NutriMax"
desc = "A plant nutrients vendor"
- product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!"
- product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..."
+ slogan_list = list("Aren't you glad you don't have to fertilize the natural way?","Now with 50% less stink!","Plants are people too!")
+ ads_list = list("We like plants!","Don't you want some?","The greenest thumbs ever.","We like big plants.","Soft soil...")
icon_state = "nutri"
icon_deny = "nutri-deny"
products = list(/obj/item/reagent_containers/glass/bottle/nutrient/ez = 30,/obj/item/reagent_containers/glass/bottle/nutrient/l4z = 20,/obj/item/reagent_containers/glass/bottle/nutrient/rh = 10,/obj/item/reagent_containers/spray/pestspray = 20,
@@ -1284,8 +1275,8 @@
/obj/machinery/vending/hydroseeds
name = "\improper MegaSeed Servitor"
desc = "When you need seeds fast!"
- product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
- product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
+ slogan_list = list("THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!","Hands down the best seed selection on the station!","Also certain mushroom varieties available, more for experts! Get certified today!")
+ ads_list = list("We like plants!","Grow some crops!","Grow, baby, growww!","Aw h'yeah son!")
icon_state = "seeds"
products = list(/obj/item/seeds/aloe =3,
/obj/item/seeds/ambrosia = 3,
@@ -1354,10 +1345,10 @@
name = "\improper MagiVend"
desc = "A magic vending machine."
icon_state = "MagiVend"
- product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!"
+ slogan_list = list("Sling spells the proper way with MagiVend!","Be your own Houdini! Use MagiVend!")
vend_delay = 15
vend_reply = "Have an enchanted evening!"
- product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!"
+ ads_list = list("FJKLFJSD","AJKFLBJAKL","1234 LOONIES LOL!",">MFW","Kill them fuckers!","GET DAT FUKKEN DISK","HONK!","EI NATH","Destroy the station!","Admin conspiracies since forever!","Space-time bending hardware!")
products = list(/obj/item/clothing/head/wizard = 1,
/obj/item/clothing/suit/wizrobe = 1,
/obj/item/clothing/head/wizard/red = 1,
@@ -1367,6 +1358,10 @@
/obj/item/clothing/head/wizard/clown = 1,
/obj/item/clothing/mask/gas/clownwiz = 1,
/obj/item/clothing/shoes/clown_shoes/magical = 1,
+ /obj/item/clothing/suit/wizrobe/mime = 1,
+ /obj/item/clothing/head/wizard/mime = 1,
+ /obj/item/clothing/mask/gas/mime/wizard = 1,
+ /obj/item/clothing/shoes/sandal/marisa = 1,
/obj/item/twohanded/staff = 2)
contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
@@ -1377,7 +1372,7 @@
desc = "A vending machine for costumes."
icon_state = "theater"
icon_deny = "theater-deny"
- product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!"
+ slogan_list = list("Dress for success!","Suited and booted!","It's show time!","Why leave style up to fate? Use AutoDrobe!")
vend_delay = 15
vend_reply = "Thank you for using AutoDrobe!"
products = list(/obj/item/clothing/suit/chickensuit = 1,
@@ -1519,7 +1514,7 @@
/obj/machinery/vending/dinnerware
name = "\improper Plasteel Chef's Dinnerware Vendor"
desc = "A kitchen and restaurant equipment vendor."
- product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
+ ads_list = list("Mm, food stuffs!","Food and food accessories.","Get your plates!","You like forks?","I like forks.","Woo, utensils.","You don't really need these...")
icon_state = "dinnerware"
products = list(/obj/item/storage/bag/tray = 8,/obj/item/kitchen/utensil/fork = 6,
/obj/item/kitchen/knife = 3,/obj/item/kitchen/rollingpin = 2,
@@ -1551,7 +1546,7 @@
name = "\improper BODA"
desc = "Old sweet water vending machine."
icon_state = "sovietsoda"
- product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem."
+ ads_list = list("For Tsar and Country.","Have you fulfilled your nutrition quota today?","Very nice!","We are simple people, for this is all we eat.","If there is a person, there is a problem. If there is no person, then there is no problem.")
products = list(/obj/item/reagent_containers/food/drinks/drinkingglass/soda = 30)
contraband = list(/obj/item/reagent_containers/food/drinks/drinkingglass/cola = 20)
resistance_flags = FIRE_PROOF
@@ -1646,8 +1641,8 @@
/obj/machinery/vending/sustenance
name = "\improper Sustenance Vendor"
desc = "A vending machine which vends food, as required by section 47-C of the NT's Prisoner Ethical Treatment Agreement."
- product_slogans = "Enjoy your meal.;Enough calories to support strenuous labor."
- product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!"
+ slogan_list = list("Enjoy your meal.","Enough calories to support strenuous labor.")
+ ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!")
icon_state = "sustenance"
products = list(/obj/item/reagent_containers/food/snacks/tofu = 24,
/obj/item/reagent_containers/food/drinks/ice = 12,
@@ -1671,7 +1666,7 @@
name = "\improper Hatlord 9000"
desc = "It doesn't seem the slightest bit unusual. This frustrates you immensely."
icon_state = "hats"
- product_ads = "Warning, not all hats are dog/monkey compatible. Apply forcefully with care.;Apply directly to the forehead.;Who doesn't love spending cash on hats?!;From the people that brought you collectable hat crates, Hatlord!"
+ ads_list = list("Warning, not all hats are dog/monkey compatible. Apply forcefully with care.","Apply directly to the forehead.","Who doesn't love spending cash on hats?!","From the people that brought you collectable hat crates, Hatlord!")
products = list(/obj/item/clothing/head/bowlerhat = 10,
/obj/item/clothing/head/beaverhat = 10,
/obj/item/clothing/head/boaterhat = 10,
@@ -1695,7 +1690,7 @@
name = "\improper Suitlord 9000"
desc = "You wonder for a moment why all of your shirts and pants come conjoined. This hurts your head and you stop thinking about it."
icon_state = "suits"
- product_ads = "Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*;Blood of your enemies washes right out!;Who are YOU wearing?;Look dapper! Look like an idiot!;Dont carry your size? How about you shave off some pounds you fat lazy- *BZZT*"
+ ads_list = list("Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*","Blood of your enemies washes right out!","Who are YOU wearing?","Look dapper! Look like an idiot!","Dont carry your size? How about you shave off some pounds you fat lazy- *BZZT*")
products = list(/obj/item/clothing/under/color/black = 10,/obj/item/clothing/under/color/blue = 10,/obj/item/clothing/under/color/green = 10,/obj/item/clothing/under/color/grey = 10,/obj/item/clothing/under/color/pink = 10,/obj/item/clothing/under/color/red = 10,
/obj/item/clothing/under/color/white = 10, /obj/item/clothing/under/color/yellow = 10,/obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/aqua = 10,/obj/item/clothing/under/color/purple = 10,/obj/item/clothing/under/color/lightgreen = 10,
/obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/lightbrown = 10,/obj/item/clothing/under/color/brown = 10,/obj/item/clothing/under/color/yellowgreen = 10,/obj/item/clothing/under/color/darkblue = 10,/obj/item/clothing/under/color/lightred = 10, /obj/item/clothing/under/color/darkred = 10)
@@ -1716,7 +1711,7 @@
name = "\improper Shoelord 9000"
desc = "Wow, hatlord looked fancy, suitlord looked streamlined, and this is just normal. The guy who designed these must be an idiot."
icon_state = "shoes"
- product_ads = "Put your foot down!;One size fits all!;IM WALKING ON SUNSHINE!;No hobbits allowed.;NO PLEASE WILLY, DONT HURT ME- *BZZT*"
+ ads_list = list("Put your foot down!","One size fits all!","IM WALKING ON SUNSHINE!","No hobbits allowed.","NO PLEASE WILLY, DONT HURT ME- *BZZT*")
products = list(/obj/item/clothing/shoes/black = 10,/obj/item/clothing/shoes/brown = 10,/obj/item/clothing/shoes/blue = 10,/obj/item/clothing/shoes/green = 10,/obj/item/clothing/shoes/yellow = 10,/obj/item/clothing/shoes/purple = 10,/obj/item/clothing/shoes/red = 10,/obj/item/clothing/shoes/white = 10,/obj/item/clothing/shoes/sandal=10)
contraband = list(/obj/item/clothing/shoes/orange = 5)
premium = list(/obj/item/clothing/shoes/rainbow = 1)
@@ -1734,8 +1729,8 @@
/obj/machinery/vending/syndicigs
name = "\improper Suspicious Cigarette Machine"
desc = "Smoke 'em if you've got 'em."
- product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
- product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs."
+ slogan_list = list("Space cigs taste good like a cigarette should.","I'd rather toolbox than switch.","Smoke!","Don't believe the reports - smoke today!")
+ ads_list = list("Probably not bad for you!","Don't believe the scientists!","It's good for you!","Don't quit, buy more!","Smoke!","Nicotine heaven.","Best cigarettes since 2150.","Award-winning cigs.")
vend_delay = 34
icon_state = "cigs"
products = list(/obj/item/storage/fancy/cigarettes/syndicate = 10,/obj/item/lighter/random = 5)
@@ -1743,8 +1738,8 @@
/obj/machinery/vending/syndisnack
name = "\improper Getmore Chocolate Corp"
desc = "A modified snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars"
- product_slogans = "Try our new nougat bar!;Twice the calories for half the price!"
- product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!"
+ slogan_list = list("Try our new nougat bar!","Twice the calories for half the price!")
+ ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!")
icon_state = "snack"
products = list(/obj/item/reagent_containers/food/snacks/chips =6,/obj/item/reagent_containers/food/snacks/sosjerky = 6,
/obj/item/reagent_containers/food/snacks/syndicake = 6, /obj/item/reagent_containers/food/snacks/cheesiehonkers = 6)
@@ -1754,7 +1749,7 @@
name = "\improper ClothesMate" //renamed to make the slogan rhyme
desc = "A vending machine for clothing."
icon_state = "clothes"
- product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!"
+ slogan_list = list("Dress for success!","Prepare to look swagalicious!","Look at all this free swag!","Why leave style up to fate? Use the ClothesMate!")
vend_delay = 15
vend_reply = "Thank you for using the ClothesMate!"
products = list(/obj/item/clothing/head/that = 2,
@@ -1855,8 +1850,8 @@
/obj/machinery/vending/artvend
name = "\improper ArtVend"
desc = "A vending machine for art supplies."
- product_slogans = "Stop by for all your artistic needs!;Color the floors with crayons, not blood!;Don't be a starving artist, use ArtVend. ;Don't fart, do art!"
- product_ads = "Just like Kindergarten!;Now with 1000% more vibrant colors!;Screwing with the janitor was never so easy!;Creativity is at the heart of every spessman."
+ slogan_list = list("Stop by for all your artistic needs!","Color the floors with crayons, not blood!","Don't be a starving artist, use ArtVend. ","Don't fart, do art!")
+ ads_list = list("Just like Kindergarten!","Now with 1000% more vibrant colors!","Screwing with the janitor was never so easy!","Creativity is at the heart of every spessman.")
vend_delay = 15
icon_state = "artvend"
products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/camera = 4,/obj/item/camera_film = 6,
@@ -1870,8 +1865,8 @@
/obj/machinery/vending/crittercare
name = "\improper CritterCare"
desc = "A vending machine for pet supplies."
- product_slogans = "Stop by for all your animal's needs!;Cuddly pets deserve a stylish collar!;Pets in space, what could be more adorable?;Freshest fish eggs in the system!;Rocks are the perfect pet, buy one today!"
- product_ads = "House-training costs extra!;Now with 1000% more cat hair!;Allergies are a sign of weakness!;Dogs are man's best friend. Remember that Vulpkanin!; Heat lamps for Unathi!; Vox-y want a cracker?"
+ slogan_list = list("Stop by for all your animal's needs!","Cuddly pets deserve a stylish collar!","Pets in space, what could be more adorable?","Freshest fish eggs in the system!","Rocks are the perfect pet, buy one today!")
+ ads_list = list("House-training costs extra!","Now with 1000% more cat hair!","Allergies are a sign of weakness!","Dogs are man's best friend. Remember that Vulpkanin!"," Heat lamps for Unathi!"," Vox-y want a cracker?")
vend_delay = 15
icon_state = "crittercare"
products = list(/obj/item/clothing/accessory/petcollar = 5, /obj/item/storage/firstaid/aquatic_kit/full =5, /obj/item/fish_eggs/goldfish = 5,
@@ -1905,7 +1900,7 @@
desc = "All the parts you need to build your own custom pc."
icon_state = "modularpc"
icon_deny = "modularpc-deny"
- product_ads = "Get your gamer gear!;The best GPUs for all of your space-crypto needs!;The most robust cooling!;The finest RGB in space!"
+ ads_list = list("Get your gamer gear!","The best GPUs for all of your space-crypto needs!","The most robust cooling!","The finest RGB in space!")
vend_reply = "Game on!"
products = list(/obj/item/modular_computer/laptop = 4,
/obj/item/modular_computer/tablet = 4,
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index d9ec4412ab3..0898936cbfb 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -39,7 +39,7 @@
icon_state = "darkgygax"
initial_icon = "darkgygax"
max_integrity = 300
- deflect_chance = 15
+ deflect_chance = 20
armor = list(melee = 40, bullet = 40, laser = 50, energy = 35, bomb = 20, bio = 0, rad =20, fire = 100, acid = 100)
max_temperature = 35000
leg_overload_coeff = 100
@@ -50,16 +50,24 @@
starting_voice = /obj/item/mecha_modkit/voice/syndicate
destruction_sleep_duration = 1
+/obj/mecha/combat/gygax/dark/GrantActions(mob/living/user, human_occupant = 0)
+ . = ..()
+ thrusters_action.Grant(user, src)
+
+/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0)
+ . = ..()
+ thrusters_action.Remove(user)
+
/obj/mecha/combat/gygax/dark/loaded/New()
..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang
+ ME = new /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster
ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/teleporter/precise
+ ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
ME.attach(src)
/obj/mecha/combat/gygax/dark/add_cell()
- cell = new /obj/item/stock_parts/cell/hyper(src)
+ cell = new /obj/item/stock_parts/cell/bluespace(src)
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index 43937ab1111..61ba683ad18 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -206,6 +206,7 @@
/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
chassis.overlays -= droid_overlay
STOP_PROCESSING(SSobj, src)
+ return ..()
/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
if(!chassis) return
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 7dac9de2b9a..9acdcba48de 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -166,10 +166,6 @@
var/mob/M = A
if(istype(firer, /mob))
add_attack_logs(firer, M, "Mecha-shot with [src]")
- if(!iscarbon(firer))
- M.LAssailant = null
- else
- M.LAssailant = firer
else
add_attack_logs(null, M, "Mecha-shot with [src]")
if(life <= 0)
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 04322c63093..896ce886887 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -5,8 +5,8 @@
/turf/simulated/floor/mech_bay_recharge_floor/airless
icon_state = "recharge_floor_asteroid"
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/obj/machinery/mech_bay_recharge_port
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 90256fe5d2a..50fdfef3cb3 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -38,9 +38,7 @@
)
/obj/machinery/mecha_part_fabricator/New()
- var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
- list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0,
- FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
+ var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
..()
component_parts = list()
@@ -65,7 +63,7 @@
RefreshParts()
/obj/machinery/mecha_part_fabricator/Destroy()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
@@ -75,7 +73,7 @@
//maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = (200000 + (T*50000))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
@@ -118,7 +116,7 @@
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
output += "[M.name]: [M.amount] cm³"
@@ -139,7 +137,7 @@
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs.
return FALSE
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE
return FALSE
@@ -149,7 +147,7 @@
desc = "It's building \a [initial(D.name)]."
var/list/res_coef = get_resources_w_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount(res_coef)
overlays += "fab-active"
use_power = ACTIVE_POWER_USE
@@ -392,7 +390,7 @@
var/index = afilter.getNum("index")
var/new_index = index + afilter.getNum("queue_move")
if(isnum(index) && isnum(new_index))
- if(IsInRange(new_index,1,queue.len))
+ if(ISINRANGE(new_index,1,queue.len))
queue.Swap(index,new_index)
return update_queue_on_page()
if(href_list["clear_queue"])
@@ -414,7 +412,7 @@
break
if(href_list["remove_mat"] && href_list["material"])
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"])
updateUsrDialog()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index ddc2a44b278..540e1074844 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1,3 +1,5 @@
+#define OCCUPANT_LOGGING occupant ? occupant : "empty mech"
+
/obj/mecha
name = "Mecha"
desc = "Exosuit"
@@ -11,6 +13,7 @@
force = 5
max_integrity = 300 //max_integrity is base health
armor = list(melee = 20, bullet = 10, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 100)
+ bubble_icon = "machine"
var/list/facing_modifiers = list(MECHA_FRONT_ARMOUR = 1.5, MECHA_SIDE_ARMOUR = 1, MECHA_BACK_ARMOUR = 0.5)
var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming.
var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
@@ -35,6 +38,8 @@
var/lights = 0
var/lights_power = 6
var/emagged = FALSE
+ var/frozen = FALSE
+ var/repairing = FALSE
//inner atmos
var/use_internal_tank = 0
@@ -263,7 +268,7 @@
return 1
/obj/mecha/relaymove(mob/user, direction)
- if(!direction)
+ if(!direction || frozen)
return
if(user != occupant) //While not "realistic", this piece is player friendly.
user.forceMove(get_turf(src))
@@ -540,7 +545,8 @@
/obj/mecha/attack_alien(mob/living/user)
- log_message("Attack by alien. Attacker - [user].", color = "red")
+ log_message("Attack by alien. Attacker - [user].", TRUE)
+ add_attack_logs(user, OCCUPANT_LOGGING, "Alien attacked mech [src]")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, TRUE)
attack_generic(user, 15, BRUTE, "melee", 0)
@@ -558,8 +564,8 @@
if(user.obj_damage)
animal_damage = user.obj_damage
animal_damage = min(animal_damage, 20*user.environment_smash)
- user.create_attack_log("attacked [name]")
- add_attack_logs(user, src, "Attacked")
+ if(animal_damage)
+ add_attack_logs(user, OCCUPANT_LOGGING, "Animal attacked mech [src]")
attack_generic(user, animal_damage, user.melee_damage_type, "melee", play_soundeffect)
return TRUE
@@ -570,7 +576,7 @@
. = ..()
if(.)
log_message("Attack by hulk. Attacker - [user].", 1)
- add_attack_logs(user, src, "Punched with hulk powers")
+ add_attack_logs(user, OCCUPANT_LOGGING, "Hulk punched mech [src]")
/obj/mecha/blob_act(obj/structure/blob/B)
log_message("Attack by blob. Attacker - [B].")
@@ -581,10 +587,14 @@
/obj/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper
log_message("Hit by [AM].")
+ if(isitem(AM))
+ var/obj/item/I = AM
+ add_attack_logs(I.thrownby, OCCUPANT_LOGGING, "threw [AM] at mech [src]")
. = ..()
/obj/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).")
+ add_attack_logs(Proj.firer, OCCUPANT_LOGGING, "shot [Proj.name]([Proj.flag]) at mech [src]")
..()
/obj/mecha/ex_act(severity, target)
@@ -608,6 +618,8 @@
occupant = null
icon_state = initial(icon_state)+"-open"
setDir(dir_in)
+ if(A in trackers)
+ trackers -= A
/obj/mecha/Destroy()
if(occupant)
@@ -638,7 +650,7 @@
cabin_air = null
QDEL_NULL(spark_system)
QDEL_NULL(smoke_system)
-
+ QDEL_LIST(trackers)
GLOB.mechas_list -= src //global mech list
return ..()
@@ -769,6 +781,8 @@
to_chat(user, "You stop installing [M].")
else
+ if(W.force)
+ add_attack_logs(user, OCCUPANT_LOGGING, "attacked mech '[src]' using [W]")
return ..()
@@ -835,7 +849,11 @@
if((obj_integrity >= max_integrity) && !internal_damage)
to_chat(user, "[src] is at full integrity!")
return
+ if(repairing)
+ to_chat(user, "[src] is currently being repaired!")
+ return
WELDER_ATTEMPT_REPAIR_MESSAGE
+ repairing = TRUE
if(I.use_tool(src, user, 15, volume = I.tool_volume))
if(internal_damage & MECHA_INT_TANK_BREACH)
clearInternalDamage(MECHA_INT_TANK_BREACH)
@@ -845,6 +863,7 @@
obj_integrity += min(10, max_integrity - obj_integrity)
else
to_chat(user, "[src] is at full integrity!")
+ repairing = FALSE
/obj/mecha/mech_melee_attack(obj/mecha/M)
if(!has_charge(melee_energy_drain))
@@ -1049,6 +1068,9 @@
log_message("Now taking air from [use_internal_tank ? "internal airtank" : "environment"].")
/obj/mecha/MouseDrop_T(mob/M, mob/user)
+ if(frozen)
+ to_chat(user, "Do not enter Admin-Frozen mechs.")
+ return
if(user.incapacitated())
return
if(user != M)
@@ -1094,11 +1116,10 @@
to_chat(user, "You stop entering the exosuit!")
/obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob)
- if(H && H.client && H in range(1))
+ if(H && H.client && (H in range(1)))
occupant = H
H.stop_pulling()
H.forceMove(src)
- H.reset_perspective(src)
add_fingerprint(H)
GrantActions(H, human_occupant = 1)
forceMove(loc)
@@ -1141,7 +1162,7 @@
return 0
/obj/mecha/proc/mmi_moved_inside(obj/item/mmi/mmi_as_oc,mob/user)
- if(mmi_as_oc && user in range(1))
+ if(mmi_as_oc && (user in range(1)))
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
to_chat(user, "Consciousness matrix not detected.")
return 0
@@ -1441,8 +1462,10 @@
diag_hud_set_mechtracking()
-/obj/mecha/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
- flick_overlay(image('icons/mob/talk.dmi', bubble_loc, bubble_state,MOB_LAYER+1), bubble_recipients, 30)
+/obj/mecha/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
+ var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, FLY_LAYER)
+ I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
+ INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, bubble_recipients, 30)
/obj/mecha/update_remote_sight(mob/living/user)
if(occupant_sight_flags)
@@ -1451,7 +1474,7 @@
..()
-/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
+/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect)
if(selected)
used_item = selected
@@ -1520,3 +1543,5 @@
if(L.incapacitated())
return FALSE
return TRUE
+
+#undef OCCUPANT_LOGGING
diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm
index 9a3dffb0c3b..f72770a8ea3 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/game/mecha/mecha_control_console.dm
@@ -28,7 +28,12 @@
data["screen"] = screen
if(screen == 0)
var/list/mechas[0]
- for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
+ var/list/trackerlist = list()
+ for(var/stompy in GLOB.mechas_list)
+ var/obj/mecha/MC = stompy
+ trackerlist += MC.trackers
+ for(var/thing in trackerlist)
+ var/obj/item/mecha_parts/mecha_tracking/TR = thing
var/answer = TR.get_mecha_info()
if(answer)
mechas[++mechas.len] = answer
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 0b106f2ab4c..7569d8b5263 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -124,8 +124,7 @@
//Attach hydraulic clamp
var/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/HC = new
HC.attach(src)
- for(var/obj/item/mecha_parts/mecha_tracking/B in trackers)//Deletes the beacon so it can't be found easily
- qdel(B)
+ QDEL_LIST(trackers) //Deletes the beacon so it can't be found easily
var/obj/item/mecha_parts/mecha_equipment/mining_scanner/scanner = new
scanner.attach(src)
@@ -139,7 +138,7 @@
..()
if(href_list["drop_from_cargo"])
var/obj/O = locate(href_list["drop_from_cargo"])
- if(O && O in cargo)
+ if(O && (O in cargo))
occupant_message("You unload [O].")
O.loc = get_turf(src)
cargo -= O
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index bb1070f2cf1..e3c14ff459c 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -11,7 +11,7 @@
/atom/movable/attack_hand(mob/living/user)
. = ..()
if(can_buckle && has_buckled_mobs())
- if(buckled_mobs.len > 1)
+ if(length(buckled_mobs) > 1)
var/unbuckled = input(user, "Who do you wish to unbuckle?", "Unbuckle Who?") as null|mob in buckled_mobs
if(user_unbuckle_mob(unbuckled,user))
return TRUE
@@ -26,15 +26,12 @@
return TRUE
/atom/movable/proc/has_buckled_mobs()
- if(!buckled_mobs)
- return FALSE
- if(buckled_mobs.len)
- return TRUE
+ return length(buckled_mobs)
/atom/movable/attack_robot(mob/living/user)
. = ..()
if(can_buckle && has_buckled_mobs() && Adjacent(user)) // attack_robot is called on all ranges, so the Adjacent check is needed
- if(buckled_mobs.len > 1)
+ if(length(buckled_mobs) > 1)
var/unbuckled = input(user, "Who do you wish to unbuckle?", "Unbuckle Who?") as null|mob in buckled_mobs
if(user_unbuckle_mob(unbuckled,user))
return TRUE
@@ -54,7 +51,7 @@
if(check_loc && M.loc != loc)
return FALSE
- if((!can_buckle && !force) || M.buckled || (buckled_mobs.len >= max_buckled_mobs) || (buckle_requires_restraints && !M.restrained()) || M == src)
+ if((!can_buckle && !force) || M.buckled || (length(buckled_mobs) >= max_buckled_mobs) || (buckle_requires_restraints && !M.restrained()) || M == src)
return FALSE
M.buckling = src
if(!M.can_buckle() && !force)
@@ -69,6 +66,9 @@
if(buckle_prevents_pull)
M.pulledby.stop_pulling()
+ for(var/obj/item/grab/G in M.grabbed_by)
+ qdel(G)
+
if(!check_loc && M.loc != loc)
M.forceMove(loc)
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 7e626584780..b7eea1b367f 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -86,7 +86,7 @@ GLOBAL_LIST_EMPTY(splatter_cache)
user.blood_DNA |= blood_DNA.Copy()
user.bloody_hands += taken
user.hand_blood_color = basecolor
- user.update_inv_gloves(1)
+ user.update_inv_gloves()
user.verbs += /mob/living/carbon/human/proc/bloody_doodle
/obj/effect/decal/cleanable/blood/can_bloodcrawl_in()
@@ -112,7 +112,8 @@ GLOBAL_LIST_EMPTY(splatter_cache)
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
- icon_state = "ltrails_1"
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "nothing"
desc = "Your instincts say you shouldn't be following these."
gender = PLURAL
density = FALSE
diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm
index 9a879a02da3..e750c15e761 100644
--- a/code/game/objects/effects/decals/remains.dm
+++ b/code/game/objects/effects/decals/remains.dm
@@ -28,6 +28,12 @@
icon_state = "remainsrobot"
anchored = TRUE
+/obj/effect/decal/remains/robot/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["glass"] += 2
+ C.stored_comms["metal"] += 3
+ qdel(src)
+ return TRUE
+
/obj/effect/decal/remains/slime
name = "You shouldn't see this"
desc = "Noooooooooooooooooooooo"
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 9907e903970..a55c2a731eb 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -1134,7 +1134,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
qdel(src)
/obj/structure/foamedmetal/attack_alien(mob/living/carbon/alien/humanoid/M)
- M.visible_message("[M] tears apart \the [src]!");
+ M.visible_message("[M] tears apart \the [src]!")
qdel(src)
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5)
diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm
index 5ae6b0c6860..9ae89309eed 100644
--- a/code/game/objects/effects/effect_system/effect_system.dm
+++ b/code/game/objects/effects/effect_system/effect_system.dm
@@ -49,6 +49,8 @@ would spawn and follow the beaker, even if it is carried or thrown.
holder = atom
/datum/effect_system/proc/start()
+ if(QDELETED(src))
+ return
for(var/i in 1 to number)
if(total_effects > 20)
return
@@ -68,7 +70,8 @@ would spawn and follow the beaker, even if it is carried or thrown.
for(var/j in 1 to steps_amt)
sleep(5)
step(E,direction)
- addtimer(CALLBACK(src, .proc/decrement_total_effect), 20)
+ if(!QDELETED(src))
+ addtimer(CALLBACK(src, .proc/decrement_total_effect), 20)
/datum/effect_system/proc/decrement_total_effect()
total_effects--
diff --git a/code/game/objects/effects/manifest.dm b/code/game/objects/effects/manifest.dm
index f267494496e..6ada54e75f7 100644
--- a/code/game/objects/effects/manifest.dm
+++ b/code/game/objects/effects/manifest.dm
@@ -10,7 +10,8 @@
/obj/effect/manifest/proc/manifest()
var/dat = "Crew Manifest: "
- for(var/mob/living/carbon/human/M in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/M = thing
dat += text(" [] - [] ", M.name, M.get_assignment())
var/obj/item/paper/P = new /obj/item/paper( src.loc )
P.info = dat
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 434c0af1136..a0006fd00d6 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -88,7 +88,7 @@
name = "horrific experiment"
desc = "Some sort of pod filled with blood and vicerea. You swear you can see it moving..."
icon = 'icons/obj/cloning.dmi'
- icon_state = "pod_g"
+ icon_state = "pod_mess"
//Makes a tile fully lit no matter what
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index f8abaa7a17e..4978a4ee314 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -7,6 +7,7 @@
var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect)
/obj/effect/spawner/lootdrop/New()
+ ..()
if(loot && loot.len)
for(var/i = lootcount, i > 0, i--)
if(!loot.len) break
@@ -15,7 +16,7 @@
loot.Remove(lootspawn)
if(lootspawn)
- new lootspawn(get_turf(src))
+ new lootspawn(loc)
qdel(src)
/obj/effect/spawner/lootdrop/armory_contraband
diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm
index b32688dbb83..9eb8e9de1a2 100644
--- a/code/game/objects/effects/spawners/random_spawners.dm
+++ b/code/game/objects/effects/spawners/random_spawners.dm
@@ -289,7 +289,6 @@
/obj/item/clothing/glasses/thermal = 1,
/obj/item/chameleon = 1,
/obj/item/reagent_containers/hypospray/autoinjector/stimulants = 1,
- /obj/item/storage/box/syndie_kit/atmosn2ogrenades = 1,
/obj/item/grenade/plastic/x4 = 1)
@@ -304,11 +303,6 @@
/turf/simulated/wall/mineral/plastitanium/nodiagonal = 2,
/obj/structure/falsewall/plastitanium = 2)
-/obj/effect/spawner/random_spawners/syndicate/layout/door/secret
- name = "50pc falsewall 50pc wall"
- result = list(/turf/simulated/wall/mineral/plastitanium/nodiagonal = 1,
- /obj/structure/falsewall/plastitanium = 1)
-
/obj/effect/spawner/random_spawners/syndicate/layout/door/vault
name = "80pc vaultdoor 20pc wall"
result = list(/obj/machinery/door/airlock/hatch/syndicate/vault = 4,
diff --git a/code/game/objects/effects/spawners/vaultspawner.dm b/code/game/objects/effects/spawners/vaultspawner.dm
index 0d882cc9bd2..a78c6111eb7 100644
--- a/code/game/objects/effects/spawners/vaultspawner.dm
+++ b/code/game/objects/effects/spawners/vaultspawner.dm
@@ -21,6 +21,7 @@
if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY)
new /turf/simulated/wall/vault(locate(i,j,z),type)
else
- new /turf/simulated/floor/vault(locate(i,j,z),type)
+ var/turf/T = new /turf/simulated/floor/vault(locate(i, j, z))
+ T.icon_state = "[type]vault"
qdel(src)
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index d97663759af..9dd1c771b17 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -98,6 +98,7 @@
pixel_x = rand(6,-6)
pixel_y = rand(6,-6)
START_PROCESSING(SSobj, src)
+ AddComponent(/datum/component/swarming)
/obj/structure/spider/spiderling/Destroy()
STOP_PROCESSING(SSobj, src)
@@ -189,6 +190,16 @@
to_chat(S, "You are a spider who is loyal to [S.master_commander], obey [S.master_commander]'s every order and assist [S.master_commander.p_them()] in completing [S.master_commander.p_their()] goals at any cost.")
qdel(src)
+/obj/structure/spider/spiderling/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!istype(user, /mob/living/silicon/robot/drone))
+ user.visible_message("[user] sucks [src] into its decompiler. There's a horrible crunching noise.", \
+ "It's a bit of a struggle, but you manage to suck [user] into your decompiler. It makes a series of visceral crunching noises.")
+ C.stored_comms["wood"] += 2
+ C.stored_comms["glass"] += 2
+ qdel(src)
+ return TRUE
+ return ..()
+
/obj/effect/decal/cleanable/spiderling_remains
name = "spiderling remains"
desc = "Green squishy mess."
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index 0a47e57112e..bde6cb538df 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -51,7 +51,7 @@
var/list/affecting = list()
/obj/effect/step_trigger/thrower/Trigger(atom/A)
- if(!A || !ismovableatom(A))
+ if(!A || !ismovable(A))
return
var/atom/movable/AM = A
var/curtiles = 0
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index b10a072389a..1b31891e537 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,7 +1,6 @@
//TODO: Flash range does nothing currently
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0, silent = 0, smoke = 1, cause = null, breach = TRUE)
- src = null //so we don't abort once src is deleted
epicenter = get_turf(epicenter)
// Archive the uncapped explosion for the doppler array
@@ -89,7 +88,7 @@
var/turf/T = A
if(!T)
continue
- var/dist = hypotenuse(T.x, T.y, x0, y0)
+ var/dist = HYPOTENUSE(T.x, T.y, x0, y0)
if(config.reactionary_explosions)
var/turf/Trajectory = T
@@ -210,7 +209,7 @@
var/list/wipe_colours = list()
for(var/turf/T in spiral_range_turfs(max_range, epicenter))
wipe_colours += T
- var/dist = hypotenuse(T.x, T.y, x0, y0)
+ var/dist = HYPOTENUSE(T.x, T.y, x0, y0)
if(newmode == "Yes")
var/turf/TT = T
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index c0c5fd2f3d6..baaf0cab16b 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -19,6 +19,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
can_be_hit = FALSE
suicidal_hands = TRUE
+ var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/hitsound = null
var/usesound = null
var/throwhitsound
@@ -59,7 +60,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
var/put_on_delay = DEFAULT_ITEM_PUTON_DELAY
var/breakouttime = 0
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
- var/flags_size = 0 //flag, primarily used for clothing to determine if a fatty can wear something or not.
var/block_chance = 0
var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
@@ -99,15 +99,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc.
- var/trip_verb = TV_TRIP
- var/trip_chance = 0
-
- var/trip_stun = 0
- var/trip_weaken = 0
- var/trip_any = FALSE
- var/trip_walksafe = TRUE
- var/trip_tiles = 0
-
//Tooltip vars
var/in_inventory = FALSE //is this item equipped into an inventory slot or hand of a mob?
var/tip_timer = 0
@@ -134,10 +125,10 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
return ..()
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
- if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)))
- return 0
+ if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside))
+ return FALSE
else
- return 1
+ return TRUE
/obj/item/blob_act(obj/structure/blob/B)
if(B && B.loc == loc)
@@ -607,16 +598,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
/obj/item/proc/is_equivalent(obj/item/I)
return I == src
-/obj/item/Crossed(atom/movable/AM, oldloc)
- . = ..()
- if(prob(trip_chance) && ishuman(AM))
- var/mob/living/carbon/human/H = AM
- on_trip(H)
-
-/obj/item/proc/on_trip(mob/living/carbon/human/H)
- if(H.slip(src, trip_stun, trip_weaken, trip_tiles, trip_walksafe, trip_any, trip_verb))
- return TRUE
-
/obj/item/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
return
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index d552b3c7d8f..5f5c62abd21 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -328,3 +328,5 @@
desc = "A digital copy of the station blueprints stored in your memory."
fluffnotice = "Intellectual Property of Nanotrasen. For use in engineering cyborgs only. Wipe from memory upon departure from the station."
+/obj/item/areaeditor/blueprints/ce
+
diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm
index 77aef9bb71d..5246652aa0e 100644
--- a/code/game/objects/items/contraband.dm
+++ b/code/game/objects/items/contraband.dm
@@ -56,7 +56,7 @@
desc = "Huh."
allow_wrap = FALSE
-/obj/item/storage/pill_bottle/random_drug_bottle/New()
- ..()
+/obj/item/storage/pill_bottle/random_drug_bottle/Initialize(mapload)
+ . = ..()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/food/pill/random_drugs(src)
diff --git a/code/game/objects/items/devices/airlock_painter.dm b/code/game/objects/items/devices/airlock_painter.dm
new file mode 100644
index 00000000000..8f845f2bac6
--- /dev/null
+++ b/code/game/objects/items/devices/airlock_painter.dm
@@ -0,0 +1,81 @@
+// Airlock painter
+
+/obj/item/airlock_painter
+ name = "airlock painter"
+ desc = "An advanced autopainter preprogrammed with several paintjobs for airlocks. Use it on a completed airlock to change its paintjob."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "airlock_painter"
+ item_state = "airlock_painter"
+ flags = CONDUCT | NOBLUDGEON
+ usesound = 'sound/effects/spray2.ogg'
+ w_class = WEIGHT_CLASS_SMALL
+ slot_flags = SLOT_BELT
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 1000)
+ var/paint_setting
+
+ // All the different paint jobs that an airlock painter can apply.
+ // If the airlock you're using it on is glass, the new paint job will also be glass
+ var/list/available_paint_jobs = list(
+ "Atmospherics" = /obj/machinery/door/airlock/atmos,
+ "Command" = /obj/machinery/door/airlock/command,
+ "Engineering" = /obj/machinery/door/airlock/engineering,
+ "External" = /obj/machinery/door/airlock/external,
+ "External Maintenance"= /obj/machinery/door/airlock/maintenance/external,
+ "Freezer" = /obj/machinery/door/airlock/freezer,
+ "Maintenance" = /obj/machinery/door/airlock/maintenance,
+ "Medical" = /obj/machinery/door/airlock/medical,
+ "Mining" = /obj/machinery/door/airlock/mining,
+ "Public" = /obj/machinery/door/airlock/public,
+ "Research" = /obj/machinery/door/airlock/research,
+ "Science" = /obj/machinery/door/airlock/science,
+ "Security" = /obj/machinery/door/airlock/security,
+ "Standard" = /obj/machinery/door/airlock,
+ )
+
+//Only call this if you are certain that the painter will be used right after this check!
+/obj/item/airlock_painter/proc/paint(mob/user)
+ playsound(loc, usesound, 30, TRUE)
+ return TRUE
+
+/obj/item/airlock_painter/attack_self(mob/user)
+ paint_setting = input(user, "Please select a paintjob for this airlock.") as null|anything in available_paint_jobs
+ if(!paint_setting)
+ return
+ to_chat(user, "The [paint_setting] paint setting has been selected.")
+
+/obj/item/airlock_painter/suicide_act(mob/user)
+
+ var/obj/item/organ/internal/lungs/L = user.get_organ_slot("lungs")
+ var/lungs_name = "\improper[L.name]"
+
+ if(L)
+ user.visible_message("[user] is inhaling toner from [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ // Once you've inhaled the toner, you throw up your lungs
+ // and then die.
+
+ // they managed to lose their lungs between then and now. Good job.
+ if(!L)
+ return FALSE
+
+ L.remove(user)
+
+ // make some colorful reagent, and apply it to the lungs
+ L.create_reagents(10)
+ L.reagents.add_reagent("colorful_reagent", 10)
+ L.reagents.reaction(L, REAGENT_TOUCH, 1)
+
+ user.emote("scream")
+ user.visible_message("[user] vomits out [user.p_their()] [lungs_name]!")
+ playsound(user.loc, 'sound/effects/splat.ogg', 50, TRUE)
+
+ // make some vomit under the player, and apply colorful reagent
+ var/obj/effect/decal/cleanable/vomit/V = new(get_turf(user))
+ V.create_reagents(10)
+ V.reagents.add_reagent("colorful_reagent", 10)
+ V.reagents.reaction(V, REAGENT_TOUCH, 1)
+
+ L.forceMove(get_turf(user))
+
+ return OXYLOSS
+ else
+ return SHAME
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 7acf6b61a6d..7724d499e7e 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -54,21 +54,21 @@
user.set_machine(src)
interact(user)
-/obj/item/camera_bug/check_eye(var/mob/user as mob)
- if(user.stat || loc != user || !user.canmove || !user.has_vision() || !current)
- user.reset_perspective(null)
+/obj/item/camera_bug/check_eye(mob/user)
+ if(loc != user || user.incapacitated() || !user.has_vision() || !current)
user.unset_machine()
- return null
-
- var/turf/T = get_turf(user.loc)
- if(T.z != current.z || !current.can_use())
+ return FALSE
+ var/turf/T_user = get_turf(user.loc)
+ var/turf/T_current = get_turf(current)
+ if(!atoms_share_level(T_user, T_current) || !current.can_use())
to_chat(user, "[src] has lost the signal.")
current = null
- user.reset_perspective(null)
user.unset_machine()
- return null
+ return FALSE
+ return TRUE
- return 1
+/obj/item/camera_bug/on_unset_machine(mob/user)
+ user.reset_perspective(null)
/obj/item/camera_bug/proc/get_cameras()
if(world.time > (last_net_update + 100))
@@ -182,7 +182,6 @@
/obj/item/camera_bug/Topic(var/href,var/list/href_list)
if(usr != loc)
usr.unset_machine()
- usr.reset_perspective(null)
usr << browse(null, "window=camerabug")
return
usr.set_machine(src)
@@ -233,7 +232,6 @@
interact()
else
usr.unset_machine()
- usr.reset_perspective(null)
usr << browse(null, "window=camerabug")
return
else
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 97c5817f05b..95b36194f56 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -241,6 +241,7 @@
user.base_icon = disguise
user.icon_state = disguise
user.cham_proj = src
+ user.bubble_icon = "robot"
active = TRUE
user.update_icons()
@@ -249,6 +250,7 @@
S = user
user.base_icon = initial(user.base_icon)
user.icon_state = initial(user.icon_state)
+ user.bubble_icon = "syndibot"
active = FALSE
user.update_icons()
diff --git a/code/game/objects/items/devices/enginepicker.dm b/code/game/objects/items/devices/enginepicker.dm
index fe6bb7e8717..0fd3a591560 100644
--- a/code/game/objects/items/devices/enginepicker.dm
+++ b/code/game/objects/items/devices/enginepicker.dm
@@ -14,8 +14,12 @@
var/list/list_enginebeacons = list()
var/isactive = FALSE
+/obj/item/enginepicker/Destroy()
+ list_enginebeacons.Cut()
+ return ..()
+
/obj/item/enginepicker/attack_self(mob/living/carbon/user)
- if(usr.stat || !usr.canmove || usr.restrained())
+ if(user.incapacitated())
return
if(!isactive)
@@ -72,7 +76,7 @@
new G(T) //Spawns the switch-selected engine on the chosen beacon's turf
var/ailist[] = list()
- for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
ailist += A
if(ailist.len)
var/mob/living/silicon/ai/announcer = pick(ailist)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index af673c7b285..8bfbf22f05d 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -67,49 +67,52 @@
times_used = max(0, times_used) //sanity
-/obj/item/flash/proc/try_use_flash(var/mob/user = null)
+/obj/item/flash/proc/try_use_flash(mob/user = null)
flash_recharge(user)
if(broken)
- return 0
+ return FALSE
- playsound(src.loc, use_sound, 100, 1)
+ playsound(loc, use_sound, 100, 1)
flick("[initial(icon_state)]2", src)
+ set_light(2, 1, COLOR_WHITE)
+ addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2)
times_used++
if(user && !clown_check(user))
- return 0
+ return FALSE
- return 1
+ return TRUE
/obj/item/flash/proc/flash_carbon(var/mob/living/carbon/M, var/mob/user = null, var/power = 5, targeted = 1)
- add_attack_logs(user, M, "Flashed with [src]")
- if(user && targeted)
- if(M.weakeyes)
- M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash
- if(M.flash_eyes(1, 1))
- M.AdjustConfused(power)
- terrible_conversion_proc(M, user)
- M.Stun(1)
- visible_message("[user] blinds [M] with the flash!")
- to_chat(user, "You blind [M] with the flash!")
- to_chat(M, "[user] blinds you with the flash!")
+ if(user)
+ add_attack_logs(user, M, "Flashed with [src]")
+ if(targeted)
if(M.weakeyes)
- M.Stun(2)
- M.visible_message("[M] gasps and shields [M.p_their()] eyes!", "You gasp and shields your eyes!")
- else
- visible_message("[user] fails to blind [M] with the flash!")
- to_chat(user, "You fail to blind [M] with the flash!")
- to_chat(M, "[user] fails to blind you with the flash!")
- else
- if(M.flash_eyes())
- M.AdjustConfused(power)
+ M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash
+ if(M.flash_eyes(1, 1))
+ M.AdjustConfused(power)
+ terrible_conversion_proc(M, user)
+ M.Stun(1)
+ visible_message("[user] blinds [M] with the flash!")
+ to_chat(user, "You blind [M] with the flash!")
+ to_chat(M, "[user] blinds you with the flash!")
+ if(M.weakeyes)
+ M.Stun(2)
+ M.visible_message("[M] gasps and shields [M.p_their()] eyes!", "You gasp and shield your eyes!")
+ else
+ visible_message("[user] fails to blind [M] with the flash!")
+ to_chat(user, "You fail to blind [M] with the flash!")
+ to_chat(M, "[user] fails to blind you with the flash!")
+ return
+
+ if(M.flash_eyes())
+ M.AdjustConfused(power)
/obj/item/flash/attack(mob/living/M, mob/user)
if(!try_use_flash(user))
return 0
-
if(iscarbon(M))
flash_carbon(M, user, 5, 1)
if(overcharged)
@@ -117,22 +120,12 @@
M.IgniteMob()
burn_out()
return 1
-
else if(issilicon(M))
- if(isrobot(M))
- var/mob/living/silicon/robot/R = M
- if(R.module) // Perhaps they didn't choose a module yet
- for(var/obj/item/borg/combat/shield/S in R.module.modules)
- if(R.activated(S))
- add_attack_logs(user, M, "Flashed with [src]")
- user.visible_message("[user] tries to overloads [M]'s sensors with the [src.name], but is blocked by [M]'s shield!", "You try to overload [M]'s sensors with the [src.name], but are blocked by [M.p_their()] shield!")
- return 1
add_attack_logs(user, M, "Flashed with [src]")
if(M.flash_eyes(affect_silicon = 1))
M.Weaken(rand(5,10))
user.visible_message("[user] overloads [M]'s sensors with the [src.name]!", "You overload [M]'s sensors with the [src.name]!")
return 1
-
user.visible_message("[user] fails to blind [M] with the [src.name]!", "You fail to blind [M] with the [src.name]!")
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 4ce64a859ec..307964ca25c 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -74,7 +74,7 @@
if(istype(H)) //robots and aliens are unaffected
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
- if(M.stat == DEAD || !eyes || M.disabilities & BLIND) //mob is dead or fully blind
+ if(M.stat == DEAD || !eyes || (BLINDNESS in M.mutations)) //mob is dead or fully blind
to_chat(user, "[M]'s pupils are unresponsive to the light!")
else if((XRAY in M.mutations) || eyes.see_in_dark >= 8) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms).
to_chat(user, "[M]'s pupils glow eerily!")
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index 095b1ea9456..cfaea9f32f9 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -138,7 +138,7 @@
log_admin("[key_name(user)] EMPd a camera with a laser pointer")
user.create_attack_log("[key_name(user)] EMPd a camera with a laser pointer")
- add_attack_logs(user, C, "EMPd with [src]")
+ add_attack_logs(user, C, "EMPd with [src]", ATKLOG_ALL)
else
outmsg = "You missed the lens of [C] with [src]."
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index d9c6d60cf54..7a6b41966a8 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -167,7 +167,7 @@
// Negative numbers will subtract
/obj/item/lightreplacer/proc/AddUses(amount = 1)
- uses = Clamp(uses + amount, 0, max_uses)
+ uses = clamp(uses + amount, 0, max_uses)
/obj/item/lightreplacer/proc/AddShards(amount = 1, user)
bulb_shards += amount
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 941e90a31ef..c6fa7b20c66 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -33,8 +33,6 @@
if(H && H.mind && H.mind.miming)
to_chat(user, "Your vow of silence prevents you from speaking.")
return
- if(H.mind)
- span = H.mind.speech_span
if((COMIC in H.mutations) || H.get_int_organ(/obj/item/organ/internal/cyberimp/brain/clown_voice))
span = "sans"
if(spamcheck)
diff --git a/code/game/objects/items/devices/pizza_bomb.dm b/code/game/objects/items/devices/pizza_bomb.dm
index c12331b2be2..e5c237938d6 100644
--- a/code/game/objects/items/devices/pizza_bomb.dm
+++ b/code/game/objects/items/devices/pizza_bomb.dm
@@ -27,7 +27,7 @@
desc = "A box suited for pizzas."
icon_state = "pizzabox1"
return
- timer = Clamp(timer, 10, 100)
+ timer = clamp(timer, 10, 100)
icon_state = "pizzabox1"
to_chat(user, "You set the timer to [timer / 10] before activating the payload and closing \the [src].")
message_admins("[key_name_admin(usr)] has set a timer on a pizza bomb to [timer/10] seconds at (JMP).")
@@ -52,7 +52,7 @@
if(disarmed)
visible_message("[bicon(src)] Sparks briefly jump out of the [correct_wire] wire on \the [src], but it's disarmed!")
return
- src.audible_message("[bicon(src)] [src] beeps, \"Enjoy the pizza!\"")
+ atom_say("Enjoy the pizza!")
src.visible_message("\The [src] violently explodes!")
explosion(src.loc,1,2,4,flame_range = 2) //Identical to a minibomb
qdel(src)
diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm
index 517f9f595c5..aa123930323 100644
--- a/code/game/objects/items/devices/radio/beacon.dm
+++ b/code/game/objects/items/devices/radio/beacon.dm
@@ -69,8 +69,8 @@
to_chat(user, "Locked In")
new /obj/machinery/power/singularity_beacon/syndicate( user.loc )
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
+ user.drop_item()
qdel(src)
- return
/obj/item/radio/beacon/syndicate/bomb
name = "suspicious beacon"
@@ -82,16 +82,21 @@
to_chat(user, "Locked In")
new /obj/machinery/syndicatebomb( user.loc )
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
+ user.drop_item()
qdel(src)
- return
/obj/item/radio/beacon/engine
desc = "A label on it reads: Warning: This device is used for transportation of high-density objects used for high-yield power generation. Stay away!."
anchored = 1 //Let's not move these around. Some folk might get the idea to use these for assassinations
var/list/enginetype = list()
-/obj/item/radio/beacon/engine/Initialize()
+/obj/item/radio/beacon/engine/Initialize(mapload)
LAZYADD(GLOB.engine_beacon_list, src)
+ return ..()
+
+/obj/item/radio/beacon/engine/Destroy()
+ GLOB.engine_beacon_list -= src
+ return ..()
/obj/item/radio/beacon/engine/tesling
name = "Engine Beacon for Tesla and Singularity"
diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm
index 083720f0e22..284ce8d5598 100644
--- a/code/game/objects/items/devices/radio/electropack.dm
+++ b/code/game/objects/items/devices/radio/electropack.dm
@@ -65,7 +65,7 @@
else if(href_list["code"])
code += text2num(href_list["code"])
code = round(code)
- code = Clamp(code, 1, 100)
+ code = clamp(code, 1, 100)
else if(href_list["power"])
on = !on
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 72e584e91aa..691c12e1347 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -21,6 +21,7 @@
var/ks1type = null
var/ks2type = null
dog_fashion = null
+ requires_tcomms = TRUE
/obj/item/radio/headset/New()
..()
@@ -88,6 +89,8 @@
/obj/item/radio/headset/syndicate
origin_tech = "syndicate=3"
ks1type = /obj/item/encryptionkey/syndicate/nukeops
+ requires_tcomms = FALSE
+ instant = TRUE // Work instantly if there are no comms
/obj/item/radio/headset/syndicate/alt //undisguised bowman with flash protection
name = "syndicate headset"
@@ -103,6 +106,13 @@
/obj/item/radio/headset/syndicate/alt/syndteam
ks1type = /obj/item/encryptionkey/syndteam
+/obj/item/radio/headset/syndicate/alt/lavaland
+ name = "syndicate lavaland headset"
+
+/obj/item/radio/headset/syndicate/alt/lavaland/New()
+ . = ..()
+ set_frequency(SYND_FREQ)
+
/obj/item/radio/headset/binary
origin_tech = "syndicate=3"
ks1type = /obj/item/encryptionkey/binary
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 13c97f26730..59d2c2a99bd 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -46,16 +46,15 @@
name = "station intercom (Security)"
frequency = SEC_I_FREQ
-/obj/item/radio/intercom/New(turf/loc, ndir, building = 3)
- ..()
+/obj/item/radio/intercom/New(turf/loc, direction, building = 3)
+ . = ..()
buildstage = building
if(buildstage)
START_PROCESSING(SSobj, src)
else
- if(ndir)
- pixel_x = (ndir & EAST|WEST) ? (ndir == EAST ? 28 : -28) : 0
- pixel_y = (ndir & NORTH|SOUTH) ? (ndir == NORTH ? 28 : -28) : 0
- dir=ndir
+ if(direction)
+ setDir(direction)
+ set_pixel_offsets_from_dir(28, -28, 28, -28)
b_stat=1
on = 0
GLOB.global_intercoms.Add(src)
@@ -204,7 +203,7 @@
STOP_PROCESSING(SSobj, src)
/obj/item/radio/intercom/welder_act(mob/user, obj/item/I)
- if(!buildstage)
+ if(buildstage != 0)
return
. = TRUE
if(!I.tool_use_check(user, 3))
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 900b3449b27..b497bc518b0 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -58,6 +58,9 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
var/datum/radio_frequency/radio_connection
var/list/datum/radio_frequency/secure_radio_connections = new
+ var/requires_tcomms = FALSE // Does this device require tcomms to work.If TRUE it wont function at all without tcomms. If FALSE, it will work without tcomms, just slowly
+ var/instant = FALSE // Should this device instantly communicate if there isnt tcomms
+
/obj/item/radio/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
@@ -223,7 +226,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
channels[chan_name] |= FREQ_LISTENING
. = 1
else if(href_list["spec_freq"])
- var freq = href_list["spec_freq"]
+ var/freq = href_list["spec_freq"]
if(has_channel_access(usr, freq))
set_frequency(text2num(freq))
. = 1
@@ -233,7 +236,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
add_fingerprint(usr)
-/obj/item/radio/proc/autosay(var/message, var/from, var/channel, var/zlevel = config.contact_levels, var/role = "Unknown") //BS12 EDIT
+/obj/item/radio/proc/autosay(message, from, channel, role = "Unknown") //BS12 EDIT
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if(channel == "department")
@@ -258,10 +261,29 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
if(jammed)
message = Gibberish(message, 100)
var/list/message_pieces = message_to_multilingual(message)
- Broadcast_Message(connection, A,
- 0, "*garbled automated announcement*", src,
- message_pieces, from, "Automated Announcement", from, "synthesized voice",
- 4, 0, zlevel, connection.frequency, follow_target = follow_target)
+
+ // Make us a message datum!
+ var/datum/tcomms_message/tcm = new
+ tcm.connection = connection
+ tcm.sender = A
+ tcm.radio = src
+ tcm.sender_name = from
+ tcm.message_pieces = message_pieces
+ tcm.sender_job = "Automated Announcement"
+ tcm.vname = "synthesized voice"
+ tcm.data = SIGNALTYPE_AINOTRACK
+ // Datum radios dont have a location (obviously)
+ if(loc && loc.z)
+ tcm.source_level = loc.z // For anyone that reads this: This used to pull from a LIST from the CONFIG DATUM. WHYYYYYYYYY!!!!!!!! -aa
+ else
+ tcm.source_level = 1 // Assume Z1 if we dont have an actual Z level available to us.
+ tcm.freq = connection.frequency
+ tcm.follow_target = follow_target
+
+ // Now put that through the stuff
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ C.handle_message(tcm)
+ qdel(tcm) // Delete the message datum
qdel(A)
// Just a dummy mob used for making announcements, so we don't create AIs to do this
@@ -273,7 +295,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
universal_speak = 1
/mob/living/automatedannouncer/New()
- lifetime_timer = addtimer(CALLBACK(src, .proc/autocleanup), SecondsToTicks(10), TIMER_STOPPABLE)
+ lifetime_timer = addtimer(CALLBACK(src, .proc/autocleanup), 10 SECONDS, TIMER_STOPPABLE)
..()
/mob/living/automatedannouncer/Destroy()
@@ -318,48 +340,32 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
if(!M.IsVocal())
return 0
- /* Quick introduction:
- This new radio system uses a very robust FTL signaling technology unoriginally
- dubbed "subspace" which is somewhat similar to 'blue-space' but can't
- actually transmit large mass. Headsets are the only radio devices capable
- of sending subspace transmissions to the Communications Satellite.
-
- A headset sends a signal to a subspace listener/receiver elsewhere in space,
- the signal gets processed and logged, and an audible transmission gets sent
- to each individual headset.
- */
-
- //#### Grab the connection datum ####//
- var/message_mode = handle_message_mode(M, message_pieces, channel)
- switch(message_mode) //special cases
- if(RADIO_CONNECTION_FAIL)
- return 0
- if(RADIO_CONNECTION_NON_SUBSPACE)
- return 1
-
- if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection
- return 0
-
- var/datum/radio_frequency/connection = message_mode
- var/turf/position = get_turf(src)
-
var/jammed = FALSE
- for(var/obj/item/jammer/jammer in GLOB.active_jammers)
+ var/turf/position = get_turf(src)
+ for(var/J in GLOB.active_jammers)
+ var/obj/item/jammer/jammer = J
if(get_dist(position, get_turf(jammer)) < jammer.range)
jammed = TRUE
break
- //#### Tagging the signal with all appropriate identity values ####//
+ var/message_mode = handle_message_mode(M, message_pieces, channel)
+ switch(message_mode) //special cases
+ // This is if the connection fails
+ if(RADIO_CONNECTION_FAIL)
+ return 0
+ // This is if were using either a binary key, or a hivemind through a headset somehow. Dont ask.
+ if(RADIO_CONNECTION_NON_SUBSPACE)
+ return 1
+
+ if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection
+ return
+
+ var/datum/radio_frequency/connection = message_mode
+
// ||-- The mob's name identity --||
var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
- var/real_name = M.real_name // mob's real name
- var/mobkey = "none" // player key associated with mob
var/voicemask = 0 // the speaker is wearing a voice mask
- if(M.client)
- mobkey = M.key // assign the mob's key
-
-
var/jobname // the mob's "job"
if(jammed)
@@ -397,7 +403,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
if(ishuman(M))
var/mob/living/carbon/human/H = M
displayname = H.voice
- if(H.voice != real_name)
+ if(H.voice != M.real_name)
voicemask = TRUE
if(syndiekey && syndiekey.change_voice && connection.frequency == SYND_FREQ)
@@ -405,124 +411,50 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
jobname = "Unknown"
voicemask = TRUE
+ // Copy the message pieces so we can safely edit comms line without affecting the actual line
+ var/list/message_pieces_copy = list()
+ for(var/datum/multilingual_say_piece/S in message_pieces)
+ message_pieces_copy += new /datum/multilingual_say_piece(S.speaking, S.message)
- /* ###### Radio headsets can only broadcast through subspace ###### */
+ // Make us a message datum!
+ var/datum/tcomms_message/tcm = new
+ tcm.sender_name = displayname
+ tcm.sender_job = jobname
+ tcm.message_pieces = message_pieces_copy
+ tcm.source_level = position.z
+ tcm.freq = connection.frequency
+ tcm.vmask = voicemask
+ tcm.needs_tcomms = requires_tcomms
+ tcm.connection = connection
+ tcm.vname = M.voice_name
+ tcm.sender = M
+ // Now put that through the stuff
+ var/handled = FALSE
+ if(connection)
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ if(C.handle_message(tcm))
+ handled = TRUE
+ qdel(tcm) // Delete the message datum
+ return TRUE
- if(subspace_transmission)
- // First, we want to generate a new radio signal
- var/datum/signal/signal = new
- signal.transmission_method = 2 // 2 would be a subspace transmission.
- // transmission_method could probably be enumerated through #define. Would be neater.
+ // If we dont need tcomms and we have no connection
+ if(!requires_tcomms && !handled)
+ // If they dont need tcomms for their signal, set the type to intercoms
+ tcm.data = SIGNALTYPE_INTERCOM_SBR
+ tcm.zlevels = list(position.z)
+ if(!instant)
+ // Simulate two seconds of lag
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/broadcast_message, tcm), 20)
+ QDEL_IN(tcm, 20)
+ else
+ // Nukeops + Deathsquad headsets are instant and should work the same, whether there is comms or not
+ broadcast_message(tcm)
+ qdel(tcm) // Delete the message datum
+ return TRUE
- // --- Finally, tag the actual signal with the appropriate values ---
- signal.data = list(
- // Identity-associated tags:
- "mob" = M, // store a reference to the mob
- "mobtype" = M.type, // the mob's type
- "race" = signal.get_race(M),
- "realname" = real_name, // the mob's real name
- "name" = displayname, // the mob's display name
- "job" = jobname, // the mob's job
- "key" = mobkey, // the mob's key
- "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
- "vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mask
-
- // We store things that would otherwise be kept in the actual mob
- // so that they can be logged even AFTER the mob is deleted or something
-
- // Other tags:
- "compression" = rand(45,50), // compressed radio signal
- "message" = message_pieces, // the actual sent message
- "connection" = connection, // the radio connection to use
- "radio" = src, // stores the radio used for transmission
- "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
- "traffic" = 0, // dictates the total traffic sum that the signal went through
- "type" = 0, // determines what type of radio input it is: normal broadcast
- "server" = null, // the last server to log this signal
- "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
- "level" = position.z, // The source's z level
- "verb" = verb
- )
- signal.frequency = connection.frequency // Quick frequency set
-
- //#### Sending the signal to all subspace receivers ####//
-
- for(var/obj/machinery/telecomms/receiver/R in GLOB.telecomms_list)
- spawn(0)
- R.receive_signal(signal)
-
- // Allinone can act as receivers.
- for(var/obj/machinery/telecomms/allinone/R in GLOB.telecomms_list)
- spawn(0)
- R.receive_signal(signal)
-
- // Receiving code can be located in Telecommunications.dm
- return signal.data["done"] && position.z in signal.data["level"]
-
-
- /* ###### Intercoms and station-bounced radios ###### */
-
- var/filter_type = 2
-
- /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
- if(istype(src, /obj/item/radio/intercom))
- filter_type = 1
-
-
- var/datum/signal/signal = new
- signal.transmission_method = 2
-
-
- /* --- Try to send a normal subspace broadcast first */
-
- signal.data = list(
-
- "mob" = M, // store a reference to the mob
- "mobtype" = M.type, // the mob's type
- "race" = signal.get_race(M), // text to show next to mob in comms log console
- "realname" = real_name, // the mob's real name
- "name" = displayname, // the mob's display name
- "job" = jobname, // the mob's job
- "key" = mobkey, // the mob's key
- "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
- "vname" = M.voice_name, // the name to display if the voice wasn't understood
- "vmask" = voicemask, // 1 if the mob is using a voice gas mas
-
- "compression" = 0, // uncompressed radio signal
- "message" = message_pieces, // the actual sent message
- "connection" = connection, // the radio connection to use
- "radio" = src, // stores the radio used for transmission
- "slow" = 0,
- "traffic" = 0,
- "type" = 0,
- "server" = null,
- "reject" = 0,
- "level" = position.z,
- "verb" = verb
- )
- signal.frequency = connection.frequency // Quick frequency set
-
- for(var/obj/machinery/telecomms/receiver/R in GLOB.telecomms_list)
- spawn(0)
- R.receive_signal(signal)
-
-
- sleep(rand(10,25)) // wait a little...
-
- if(signal.data["done"] && position.z in signal.data["level"])
- // we're done here.
- return 1
-
- // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
- // Send a mundane broadcast with limited targets:
-
- //THIS IS TEMPORARY. YEAH RIGHT
- if(!connection) return 0 //~Carn
-
- return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
- src, message_pieces, displayname, jobname, real_name, M.voice_name,
- filter_type, signal.data["compression"], list(position.z), connection.frequency,verb)
+ // If we didnt get here, oh fuck
+ qdel(tcm) // Delete the message datum
+ return FALSE
/obj/item/radio/hear_talk(mob/M as mob, list/message_pieces, var/verb = "says")
@@ -696,6 +628,9 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
..()
set_frequency(ERT_FREQ)
+/obj/item/radio/borg/ert/specops
+ keyslot = new /obj/item/encryptionkey/centcom
+
/obj/item/radio/borg/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/encryptionkey/))
user.set_machine(src)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 34183a81102..f20a2cc5875 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -141,7 +141,7 @@ REAGENT SCANNER
// Used by the PDA medical scanner too
/proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE)
- if(!ishuman(M) || M.isSynthetic())
+ if(!ishuman(M) || ismachineperson(M))
//these sensors are designed for organic life
to_chat(user, "Analyzing Results for ERROR:\n\t Overall Status: ERROR")
to_chat(user, "\t Key: Suffocation/Toxin/Burns/Brute")
@@ -212,7 +212,7 @@ REAGENT SCANNER
if(H.getBrainLoss() >= 100)
to_chat(user, "Subject is brain dead.")
else if(H.getBrainLoss() >= 60)
- to_chat(user, "Severe brain damage detected. Subject likely to have mental retardation.")
+ to_chat(user, "Severe brain damage detected. Subject likely to have dementia.")
else if(H.getBrainLoss() >= 10)
to_chat(user, "Significant brain damage detected. Subject may have had a concussion.")
else
@@ -859,11 +859,11 @@ REAGENT SCANNER
dat += "
[i.name]
N/A
[i.damage]
[infection]:[mech]
"
dat += ""
dat += ""
- if(target.disabilities & BLIND)
+ if(BLINDNESS in target.mutations)
dat += "Cataracts detected. "
- if(target.disabilities & COLOURBLIND)
+ if(COLOURBLIND in target.mutations)
dat += "Photoreceptor abnormalities detected. "
- if(target.disabilities & NEARSIGHTED)
+ if(NEARSIGHTED in target.mutations)
dat += "Retinal misalignment detected. "
return dat
diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm
index 8c69402ed70..9133bf37b9c 100644
--- a/code/game/objects/items/devices/sensor_device.dm
+++ b/code/game/objects/items/devices/sensor_device.dm
@@ -6,7 +6,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
origin_tech = "programming=3;materials=3;magnets=3"
- var/datum/nano_module/crew_monitor/crew_monitor
+ var/datum/tgui_module/crew_monitor/crew_monitor
/obj/item/sensor_device/New()
..()
@@ -17,7 +17,7 @@
return ..()
/obj/item/sensor_device/attack_self(mob/user as mob)
- ui_interact(user)
+ tgui_interact(user)
-/obj/item/sensor_device/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- crew_monitor.ui_interact(user, ui_key, ui, force_open)
+/obj/item/sensor_device/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
+ crew_monitor.tgui_interact(user, ui_key, ui, force_open)
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 4aa5c4532f1..77e9eacc6a1 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -131,7 +131,6 @@ GLOBAL_LIST_EMPTY(world_uplinks)
else
var/datum/uplink_item/UI = ItemsReference[href_list["buy_item"]]
return buy(UI, UI ? UI.reference : "")
- return 0
/obj/item/uplink/proc/buy(var/datum/uplink_item/UI, var/reference)
if(!UI)
@@ -168,7 +167,6 @@ GLOBAL_LIST_EMPTY(world_uplinks)
to_chat(user, "[I] refunded.")
qdel(I)
return
- ..()
// HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it.
/* How to create an uplink in 3 easy steps!
diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm
index 0edcafd64b5..14bb468e049 100644
--- a/code/game/objects/items/flag.dm
+++ b/code/game/objects/items/flag.dm
@@ -222,7 +222,7 @@
var/input_flag = input(user, "Choose a flag to disguise as.", "Choose a flag.") in show_flag
- if(user && src in user.contents)
+ if(user && (src in user.contents))
var/obj/item/flag/chosen_flag = flag[input_flag]
diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm
index da851437fd5..1e1a39d49d0 100644
--- a/code/game/objects/items/mixing_bowl.dm
+++ b/code/game/objects/items/mixing_bowl.dm
@@ -118,7 +118,7 @@
/obj/item/mixing_bowl/Topic(href, href_list)
if(..())
return
- if("dispose")
+ if(href_list["dispose"])
dispose()
return
diff --git a/code/game/objects/items/mountable_frames/fire_alarm.dm b/code/game/objects/items/mountable_frames/fire_alarm.dm
index 83f435a277c..22c526664aa 100644
--- a/code/game/objects/items/mountable_frames/fire_alarm.dm
+++ b/code/game/objects/items/mountable_frames/fire_alarm.dm
@@ -6,5 +6,5 @@
mount_reqs = list("simfloor", "nospace")
/obj/item/mounted/frame/firealarm/do_build(turf/on_wall, mob/user)
- new /obj/machinery/firealarm(get_turf(src), get_dir(on_wall, user), 1)
+ new /obj/machinery/firealarm(get_turf(src), get_dir(user, on_wall), 1)
qdel(src)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 46bc15a2ffe..ca2fb17c004 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -253,7 +253,16 @@
to_chat(user, "This [W] does not seem to fit.")
return
- var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc), unfinished = 1)
+ var/datum/ai_laws/laws_to_give
+ if(M.syndiemmi)
+ aisync = FALSE
+ lawsync = FALSE
+ laws_to_give = new /datum/ai_laws/syndicate_override
+
+ if(!aisync)
+ lawsync = FALSE
+
+ var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc), unfinished = 1, ai_to_sync_to = forced_ai)
if(!O)
return
@@ -263,24 +272,15 @@
if(istype(task))
task.unit_completed()
- if(M.syndiemmi)
- aisync = 0
- lawsync = 0
- O.laws = new /datum/ai_laws/syndicate_override
-
O.invisibility = 0
//Transfer debug settings to new mob
O.custom_name = created_name
O.rename_character(O.real_name, O.get_default_name())
O.locked = panel_locked
- if(!aisync)
- lawsync = 0
- O.connected_ai = null
- else
- O.notify_ai(1)
- if(forced_ai)
- O.connected_ai = forced_ai
- if(!lawsync && !M.syndiemmi)
+
+ if(laws_to_give)
+ O.laws = laws_to_give
+ else if(!lawsync)
O.lawupdate = 0
O.make_laws()
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index a13bce6fb61..2d2b110fa06 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -9,23 +9,23 @@
origin_tech = "programming=2"
var/locked = 0
var/installed = 0
- var/require_module = 0
+ var/require_module = FALSE
var/module_type = null
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R)
if(R.stat == DEAD)
to_chat(usr, "[src] will not function on a deceased cyborg.")
- return 1
+ return TRUE
if(module_type && !istype(R.module, module_type))
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(usr, "There's no mounting point for the module!")
- return 1
+ return TRUE
/obj/item/borg/upgrade/reset
name = "cyborg module reset board"
desc = "Used to reset a cyborg's module. Destroys any other upgrades applied to the cyborg."
icon_state = "cyborg_upgrade1"
- require_module = 1
+ require_module = TRUE
/obj/item/borg/upgrade/reset/action(mob/living/silicon/robot/R)
if(..())
@@ -48,14 +48,14 @@
if(..())
return
if(!R.allow_rename)
- to_chat(R, "Internal diagnostic error: incompatible upgrade module detected.");
+ to_chat(R, "Internal diagnostic error: incompatible upgrade module detected.")
return 0
R.notify_ai(3, R.name, heldname)
R.name = heldname
R.custom_name = heldname
R.real_name = heldname
- return 1
+ return TRUE
/obj/item/borg/upgrade/restart
name = "cyborg emergency reboot module"
@@ -74,17 +74,17 @@
R.stat = CONSCIOUS
GLOB.dead_mob_list -= R //please never forget this ever kthx
- GLOB.living_mob_list += R
+ GLOB.alive_mob_list += R
R.notify_ai(1)
- return 1
+ return TRUE
/obj/item/borg/upgrade/vtec
name = "robotic VTEC Module"
desc = "Used to kick in a robot's VTEC systems, increasing their speed."
icon_state = "cyborg_upgrade2"
- require_module = 1
+ require_module = TRUE
origin_tech = "engineering=4;materials=5;programming=4"
/obj/item/borg/upgrade/vtec/action(var/mob/living/silicon/robot/R)
@@ -97,14 +97,14 @@
R.speed = -1 // Gotta go fast.
- return 1
+ return TRUE
/obj/item/borg/upgrade/disablercooler
name = "cyborg rapid disabler cooling module"
desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
origin_tech = "engineering=4;powerstorage=4;combat=4"
- require_module = 1
+ require_module = TRUE
module_type = /obj/item/robot_module/security
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R)
@@ -122,7 +122,7 @@
T.charge_delay = max(2 , T.charge_delay - 4)
- return 1
+ return TRUE
/obj/item/borg/upgrade/thrusters
name = "ion thruster upgrade"
@@ -139,14 +139,14 @@
return
R.ionpulse = 1
- return 1
+ return TRUE
/obj/item/borg/upgrade/ddrill
name = "mining cyborg diamond drill"
desc = "A diamond drill replacement for the mining module's standard drill."
icon_state = "cyborg_upgrade3"
origin_tech = "engineering=4;materials=5"
- require_module = 1
+ require_module = TRUE
module_type = /obj/item/robot_module/miner
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R)
@@ -161,14 +161,14 @@
R.module.modules += new /obj/item/pickaxe/drill/cyborg/diamond(R.module)
R.module.rebuild()
- return 1
+ return TRUE
/obj/item/borg/upgrade/soh
name = "mining cyborg satchel of holding"
desc = "A satchel of holding replacement for mining cyborg's ore satchel module."
icon_state = "cyborg_upgrade3"
origin_tech = "engineering=4;materials=4;bluespace=4"
- require_module = 1
+ require_module = TRUE
module_type = /obj/item/robot_module/miner
/obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R)
@@ -181,35 +181,46 @@
R.module.modules += new /obj/item/storage/bag/ore/holding(R.module)
R.module.rebuild()
- return 1
+ return TRUE
/obj/item/borg/upgrade/syndicate
- name = "illegal equipment module"
+ name = "safety override module"
desc = "Unlocks the hidden, deadlier functions of a cyborg. Also prevents emag subversion."
icon_state = "cyborg_upgrade3"
origin_tech = "combat=4;syndicate=1"
- require_module = 1
+ require_module = TRUE
/obj/item/borg/upgrade/syndicate/action(mob/living/silicon/robot/R)
if(..())
return
-
if(R.emagged)
return
-
if(R.weapons_unlock)
- to_chat(R, "Internal diagnostic error: incompatible upgrade module detected.");
+ to_chat(R, "Internal diagnostic error: incompatible upgrade module detected.")
return
-
R.emagged = 1
+ return TRUE
- return 1
+/obj/item/borg/upgrade/lavaproof
+ name = "mining cyborg lavaproof chassis"
+ desc = "An upgrade kit to apply specialized coolant systems and insulation layers to a mining cyborg's chassis, enabling them to withstand exposure to molten rock."
+ icon_state = "ash_plating"
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
+ require_module = TRUE
+ module_type = /obj/item/robot_module/miner
+
+/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R)
+ if(..())
+ return
+ if(istype(R))
+ R.weather_immunities += "lava"
+ return TRUE
/obj/item/borg/upgrade/selfrepair
name = "self-repair module"
desc = "This module will repair the cyborg over time."
icon_state = "cyborg_upgrade5"
- require_module = 1
+ require_module = TRUE
var/repair_amount = -1
var/repair_tick = 1
var/msg_cooldown = 0
@@ -230,7 +241,7 @@
icon_state = "selfrepair_off"
var/datum/action/A = new /datum/action/item_action/toggle(src)
A.Grant(R)
- return 1
+ return TRUE
/obj/item/borg/upgrade/selfrepair/Destroy()
cyborg = null
diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm
index 8b85d8821d9..9b24b1efce6 100644
--- a/code/game/objects/items/shooting_range.dm
+++ b/code/game/objects/items/shooting_range.dm
@@ -4,24 +4,23 @@
desc = "A shooting target."
icon = 'icons/obj/objects.dmi'
icon_state = "target_h"
- density = 0
+ density = FALSE
var/hp = 1800
- var/icon/virtualIcon
- var/list/bulletholes = list()
/obj/item/target/Destroy()
+ cut_overlays()
// if a target is deleted and associated with a stake, force stake to forget
- for(var/obj/structure/target_stake/T in view(3,src))
+ for(var/obj/structure/target_stake/T in view(3, src))
if(T.pinned_target == src)
T.pinned_target = null
- T.density = 1
+ T.density = TRUE
break
return ..() // delete target
/obj/item/target/Move()
..()
// After target moves, check for nearby stakes. If associated, move to target
- for(var/obj/structure/target_stake/M in view(3,src))
+ for(var/obj/structure/target_stake/M in view(3, src))
if(M.density == 0 && M.pinned_target == src)
M.loc = loc
@@ -33,12 +32,12 @@
/obj/item/target/welder_act(mob/user, obj/item/I)
. = TRUE
- if(!use_tool(src, user, 0,, volume = I.tool_volume))
+ if(!use_tool(src, user, 0, volume = I.tool_volume))
return
overlays.Cut()
- to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.")
+ to_chat(user, "You slice off [src]'s uneven chunks of aluminium and scorch marks.")
-/obj/item/target/attack_hand(mob/user as mob)
+/obj/item/target/attack_hand(mob/user)
// taking pinned targets off!
var/obj/structure/target_stake/stake
for(var/obj/structure/target_stake/T in view(3,src))
@@ -48,8 +47,8 @@
if(stake)
if(stake.pinned_target)
- stake.density = 1
- density = 0
+ stake.density = TRUE
+ density = FALSE
layer = OBJ_LAYER
loc = user.loc
@@ -77,101 +76,37 @@
desc = "A shooting target that looks like a xenomorphic alien."
hp = 2350 // alium onest too kinda
-/obj/item/target/bullet_act(var/obj/item/projectile/Proj)
- var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!"
- var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1)
- var/decaltype = 1 // 1 - scorch, 2 - bullet
+#define DECALTYPE_SCORCH 1
+#define DECALTYPE_BULLET 2
- if(istype(/obj/item/projectile/bullet, Proj))
- decaltype = 2
+/obj/item/target/bullet_act(obj/item/projectile/P)
+ var/p_x = P.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset P.p_x!"
+ var/p_y = P.p_y + pick(0,0,0,0,0,-1,1)
+ var/decaltype = DECALTYPE_SCORCH
+ if(istype(P, /obj/item/projectile/bullet))
+ decaltype = DECALTYPE_BULLET
-
- virtualIcon = new(icon, icon_state)
-
- if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null)
-
- hp -= Proj.damage
+ var/icon/C = icon(icon, icon_state)
+ if(LAZYLEN(overlays) <= 35 && C.GetPixel(p_x, p_y)) // if the located pixel isn't blank (null)
+ hp -= P.damage
if(hp <= 0)
- visible_message("[src] breaks into tiny pieces and collapses!")
+ visible_message("[src] breaks into tiny pieces and collapses!")
qdel(src)
-
- // Create a temporary object to represent the damage
- var/obj/bmark = new
- bmark.pixel_x = p_x
- bmark.pixel_y = p_y
- bmark.icon = 'icons/effects/effects.dmi'
- bmark.layer = 3.5
- bmark.icon_state = "scorch"
-
- if(decaltype == 1)
- // Energy weapons are hot. they scorch!
-
- // offset correction
- bmark.pixel_x--
- bmark.pixel_y--
-
- if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice))
- bmark.icon_state = "scorch"
- bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design
-
-
+ return
+ var/image/bullet_hole = image('icons/effects/effects.dmi', "scorch", OBJ_LAYER + 0.5)
+ bullet_hole.pixel_x = p_x - 1 //offset correction
+ bullet_hole.pixel_y = p_y - 1
+ if(decaltype == DECALTYPE_SCORCH)
+ if(P.damage >= 20 || istype(P, /obj/item/projectile/beam/practice))
+ bullet_hole.setDir(pick(NORTH,SOUTH,EAST,WEST))// random scorch design. light_scorch does not have different directions
else
- bmark.icon_state = "light_scorch"
+ bullet_hole.icon_state = "light_scorch"
else
-
- // Bullets are hard. They make dents!
- bmark.icon_state = "dent"
-
- if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes
- if(decaltype == 2) // bullet
- if(prob(Proj.damage+30)) // bullets make holes more commonly!
- new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
- else // Lasers!
- if(prob(Proj.damage-10)) // lasers make holes less commonly
- new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
-
- // draw bullet holes
- for(var/datum/bullethole/B in bulletholes)
-
- virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right
- virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom
-
- overlays += bmark // add the decal
-
- icon = virtualIcon // apply bulletholes over decals
-
+ bullet_hole.icon_state = "dent"
+ add_overlay(bullet_hole)
return
return -1 // the bullet/projectile goes through the target! Ie, you missed
-
-// Small memory holder entity for transparent bullet holes
-/datum/bullethole
- // First box
- var/b1x1 = 0
- var/b1x2 = 0
- var/b1y = 0
-
- // Second box
- var/b2x = 0
- var/b2y1 = 0
- var/b2y2 = 0
-
-/datum/bullethole/New(obj/item/target/Target, pixel_x = 0, pixel_y = 0)
- if(!Target) return
-
- // Randomize the first box
- b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4)
- b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4)
- b1y = pixel_y
- if(prob(35))
- b1y += rand(-4,4)
-
- // Randomize the second box
- b2x = pixel_x
- if(prob(35))
- b2x += rand(-4,4)
- b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4)
- b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4)
-
- Target.bulletholes.Add(src)
+#undef DECALTYPE_SCORCH
+#undef DECALTYPE_BULLET
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 59dad865acb..ff469ba3c59 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -4,6 +4,7 @@
desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery."
icon = 'icons/obj/nanopaste.dmi'
icon_state = "tube"
+ w_class = WEIGHT_CLASS_TINY
origin_tech = "materials=2;engineering=3"
amount = 6
max_amount = 6
@@ -56,7 +57,7 @@
E.heal_damage(0, remheal, 0, 1) //Healing Burn
remheal = nremheal
user.visible_message("\The [user] applies some nanite paste at \the [M]'s [E.name] with \the [src].")
- if(H.bleed_rate && H.isSynthetic())
+ if(H.bleed_rate && ismachineperson(H))
H.bleed_rate = 0
else
to_chat(user, "Nothing to fix here.")
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 4d3e3181726..000ad2d225f 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -17,9 +17,9 @@
GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe/window("directional window", /obj/structure/window/basic, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/basic, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
- new/datum/stack_recipe("fishbowl", /obj/machinery/fishtank/bowl, 1, time = 0), \
- new/datum/stack_recipe("fish tank", /obj/machinery/fishtank/tank, 3, time = 0, on_floor = TRUE), \
- new/datum/stack_recipe("wall aquariam", /obj/machinery/fishtank/wall, 4, time = 0, on_floor = TRUE) \
+ new/datum/stack_recipe("fishbowl", /obj/machinery/fishtank/bowl, 1, time = 10), \
+ new/datum/stack_recipe("fish tank", /obj/machinery/fishtank/tank, 3, time = 20, on_floor = TRUE), \
+ new/datum/stack_recipe("wall aquariam", /obj/machinery/fishtank/wall, 4, time = 40, on_floor = TRUE) \
))
/obj/item/stack/sheet/glass
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index c8e194bfb00..9f6844c8b9e 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -10,8 +10,8 @@
icon_state = "sheet-hide"
GLOBAL_LIST_INIT(human_recipes, list( \
- new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/bloated_human, 5, on_floor = 1), \
- new/datum/stack_recipe("bloated human costume head", /obj/item/clothing/head/human_head, 5, on_floor = 1), \
+ new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/bloated_human, 5, on_floor = TRUE), \
+ new/datum/stack_recipe("bloated human costume head", /obj/item/clothing/head/human_head, 5, on_floor = TRUE), \
))
/obj/item/stack/sheet/animalhide/human/New(var/loc, var/amount=null)
@@ -48,6 +48,14 @@ GLOBAL_LIST_INIT(human_recipes, list( \
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
+GLOBAL_LIST_INIT(lizard_recipes, list( \
+ new/datum/stack_recipe("lizard skin handbag", /obj/item/storage/backpack/satchel/lizard, 5, on_floor = TRUE), \
+ ))
+
+/obj/item/stack/sheet/animalhide/lizard/Initialize(mapload, new_amount, merge = TRUE)
+ recipes = GLOB.lizard_recipes
+ return ..()
+
/obj/item/stack/sheet/animalhide/xeno
name = "alien hide"
desc = "The skin of a terrible creature."
@@ -161,9 +169,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
return
if(is_type_in_typecache(target, goliath_platable_armor_typecache))
var/obj/item/clothing/C = target
- var/list/current_armor = C.armor
- if(current_armor["melee"] < 60)
- current_armor["melee"] = min(current_armor["melee"] + 10, 60)
+ var/datum/armor/current_armor = C.armor
+ if(current_armor.getRating("melee") < 60)
+ C.armor = current_armor.setRating(melee_value = min(current_armor.getRating("melee") + 10, 60))
to_chat(user, "You strengthen [target], improving its resistance against melee attacks.")
use(1)
else
@@ -172,9 +180,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
var/obj/mecha/working/ripley/D = target
if(D.hides < 3)
D.hides++
- D.armor["melee"] = min(D.armor["melee"] + 10, 70)
- D.armor["bullet"] = min(D.armor["bullet"] + 5, 50)
- D.armor["laser"] = min(D.armor["laser"] + 5, 50)
+ D.armor = D.armor.setRating(melee_value = min(D.armor.getRating("melee") + 10, 70))
+ D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating("bullet") + 5, 50))
+ D.armor = D.armor.setRating(laser_value = min(D.armor.getRating("laser") + 5, 50))
to_chat(user, "You strengthen [target], improving its resistance against melee attacks.")
D.update_icon()
if(D.hides == 3)
@@ -234,7 +242,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
HS.amount++
src.use(1)
wetness = initial(wetness)
- break
+ return
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/leather/HS = new(src.loc)
HS.amount = 1
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index b8fd23e78cb..9dabea08319 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -218,10 +218,22 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \
/obj/item/stack/sheet/mineral/plasma/welder_act(mob/user, obj/item/I)
if(I.use_tool(src, user, volume = I.tool_volume))
- message_admins("Plasma sheets ignited by [key_name_admin(user)]([ADMIN_QUE(user,"?")]) ([ADMIN_FLW(user,"FLW")]) in ([x],[y],[z] - JMP)",0,1)
- log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])")
- investigate_log("was ignited by [key_name(user)]","atmos")
- fire_act()
+ log_and_set_aflame(user, I)
+ return TRUE
+
+/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/I, mob/living/user, params)
+ if(is_hot(I))
+ log_and_set_aflame(user, I)
+ else
+ return ..()
+
+/obj/item/stack/sheet/mineral/plasma/proc/log_and_set_aflame(mob/user, obj/item/I)
+ var/turf/T = get_turf(src)
+ message_admins("Plasma sheets ignited by [key_name_admin(user)]([ADMIN_QUE(user, "?")]) ([ADMIN_FLW(user, "FLW")]) in ([COORD(T)] - [ADMIN_JMP(T)]")
+ log_game("Plasma sheets ignited by [key_name(user)] in [COORD(T)]")
+ investigate_log("was ignited by [key_name(user)]", "atmos")
+ user.create_log(MISC_LOG, "Plasma sheets ignited using [I]", src)
+ fire_act()
/obj/item/stack/sheet/mineral/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
@@ -298,13 +310,13 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
point_value = 20
-var/global/list/datum/stack_recipe/titanium_recipes = list (
+GLOBAL_LIST_INIT(titanium_recipes, list(
new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20),
new/datum/stack_recipe("surgical tray", /obj/structure/table/tray, 2, one_per_turf = 1, on_floor = 1),
- )
+ ))
/obj/item/stack/sheet/mineral/titanium/New(loc, amount=null)
- recipes = titanium_recipes
+ recipes = GLOB.titanium_recipes
..()
/obj/item/stack/sheet/mineral/titanium/fifty
@@ -328,12 +340,12 @@ var/global/list/datum/stack_recipe/titanium_recipes = list (
materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000)
point_value = 45
-var/global/list/datum/stack_recipe/plastitanium_recipes = list (
+GLOBAL_LIST_INIT(plastitanium_recipes, list(
new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20),
- )
+ ))
/obj/item/stack/sheet/mineral/plastitanium/New(loc, amount=null)
- recipes = plastitanium_recipes
+ recipes = GLOB.plastitanium_recipes
..()
/obj/item/stack/sheet/mineral/enruranium
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 14ccc103ab1..ab592cc0402 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -204,7 +204,7 @@
if(amount < 1) // Just in case a stack's amount ends up fractional somehow
var/oldsrc = src
- src = null //dont kill proc after del()
+ src = null //dont kill proc after qdel()
usr.unEquip(oldsrc, 1)
qdel(oldsrc)
if(istype(O, /obj/item))
diff --git a/code/game/objects/items/tools/tool_behaviour.dm b/code/game/objects/items/tools/tool_behaviour.dm
index 80b00dcd1ed..136bea77e6a 100644
--- a/code/game/objects/items/tools/tool_behaviour.dm
+++ b/code/game/objects/items/tools/tool_behaviour.dm
@@ -4,7 +4,7 @@
// No delay means there is no start message, and no reason to call tool_start_check before use_tool.
// Run the start check here so we wouldn't have to call it manually.
target.add_fingerprint(user)
- if(!tool_start_check(user, amount) && !delay)
+ if(!tool_start_check(target, user, amount) && !delay)
return
delay *= toolspeed
@@ -39,7 +39,7 @@
// Called before use_tool if there is a delay, or by use_tool if there isn't.
// Only ever used by welding tools and stacks, so it's not added on any other use_tool checks.
-/obj/item/proc/tool_start_check(mob/living/user, amount=0)
+/obj/item/proc/tool_start_check(atom/target, mob/living/user, amount=0)
return tool_use_check(user, amount)
// A check called by tool_start_check once, and by use_tool on every tick of delay.
@@ -57,4 +57,4 @@
// Used in a callback that is passed by use_tool into do_after call. Do not override, do not call manually.
/obj/item/proc/tool_check_callback(mob/living/user, atom/target, amount, datum/callback/extra_checks)
- return tool_use_check(user, amount) && (!extra_checks || extra_checks.Invoke())
+ return tool_use_check(user, amount) && (extra_checks && !extra_checks.Invoke())
diff --git a/code/game/objects/items/tools/welder.dm b/code/game/objects/items/tools/welder.dm
index b002ed32205..4ac934462a0 100644
--- a/code/game/objects/items/tools/welder.dm
+++ b/code/game/objects/items/tools/welder.dm
@@ -35,10 +35,12 @@
..()
create_reagents(maximum_fuel)
reagents.add_reagent("fuel", maximum_fuel)
- if(refills_over_time)
- reagents.reagents_generated_per_cycle += list("fuel" = 1)
update_icon()
+/obj/item/weldingtool/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
/obj/item/weldingtool/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 0)
@@ -49,10 +51,15 @@
return FIRELOSS
/obj/item/weldingtool/process()
- var/turf/T = get_turf(src)
- T.hotspot_expose(2500, 5)
- if(prob(5))
- remove_fuel(1)
+ if(tool_enabled)
+ var/turf/T = get_turf(src)
+ if(T) // Implants for instance won't find a turf
+ T.hotspot_expose(2500, 5)
+ if(prob(5))
+ remove_fuel(1)
+ if(refills_over_time)
+ if(GET_FUEL < maximum_fuel)
+ reagents.add_reagent("fuel", 1)
..()
/obj/item/weldingtool/attack_self(mob/user)
@@ -76,7 +83,8 @@
playsound(loc, activation_sound, 50, 1)
set_light(light_intensity)
else
- STOP_PROCESSING(SSobj, src)
+ if(!refills_over_time)
+ STOP_PROCESSING(SSobj, src)
damtype = BRUTE
force = 3
hitsound = "swing_hit"
@@ -100,9 +108,9 @@
return FALSE
// When welding is about to start, run a normal tool_use_check, then flash a mob if it succeeds.
-/obj/item/weldingtool/tool_start_check(mob/living/user, amount=0)
+/obj/item/weldingtool/tool_start_check(atom/target, mob/living/user, amount=0)
. = tool_use_check(user, amount)
- if(. && user)
+ if(. && user && !ismob(target)) // Don't flash the user if they're repairing robo limbs or repairing a borg etc. Only flash them if the target is an object
user.flash_eyes(light_intensity)
/obj/item/weldingtool/use(amount)
@@ -159,7 +167,7 @@
/obj/item/weldingtool/update_icon()
if(low_fuel_changes_icon)
var/ratio = GET_FUEL / maximum_fuel
- ratio = Ceiling(ratio*4) * 25
+ ratio = CEILING(ratio*4, 1) * 25
if(ratio == 100)
icon_state = initial(icon_state)
else
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 8e51a6760b7..66f35a169f9 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1023,6 +1023,18 @@ obj/item/toy/cards/deck/syndicate/black
name = "orange fox plushie"
icon_state = "orangefox"
+/obj/item/toy/plushie/orange_fox/grump
+ name = "grumpy fox"
+ desc = "An ancient plushie that seems particularly grumpy."
+
+/obj/item/toy/plushie/orange_fox/grump/ComponentInitialize()
+ . = ..()
+ var/static/list/grumps = list("Ahh, yes, you're so clever, var editing that.", "Really?", "If you make a runtime with var edits, it's your own damn fault.",
+ "Don't you dare post issues on the git when you don't even know how this works.", "Was that necessary?", "Ohhh, setting admin edited var must be your favorite pastime!",
+ "Oh, so you have time to var edit, but you don't have time to ban that greytider?", "Oh boy, is this another one of those 'events'?", "Seriously, just stop.", "You do realize this is incurring proc call overhead.",
+ "Congrats, you just left a reference with your dirty client and now that thing you edited will never garbage collect properly.", "Is it that time of day, again, for unecessary adminbus?")
+ AddComponent(/datum/component/edit_complainer, grumps)
+
/obj/item/toy/plushie/coffee_fox
name = "coffee fox plushie"
icon_state = "coffeefox"
@@ -1087,6 +1099,21 @@ obj/item/toy/cards/deck/syndicate/black
return
..()
+/obj/item/toy/plushie/ipcplushie
+ name = "IPC plushie"
+ desc = "An adorable IPC plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included."
+ icon_state = "plushie_ipc"
+ item_state = "plushie_ipc"
+
+/obj/item/toy/plushie/ipcplushie/attackby(obj/item/B, mob/user, params)
+ if(istype(B, /obj/item/reagent_containers/food/snacks/breadslice))
+ new /obj/item/reagent_containers/food/snacks/toast(get_turf(loc))
+ to_chat(user, " You insert bread into the toaster. ")
+ playsound(loc, 'sound/machines/ding.ogg', 50, 1)
+ qdel(B)
+ else
+ return ..()
+
//New generation TG plushies
/obj/item/toy/plushie/lizardplushie
@@ -1117,15 +1144,15 @@ obj/item/toy/cards/deck/syndicate/black
* Foam Armblade
*/
- /obj/item/toy/foamblade
- name = "foam armblade"
- desc = "it says \"Sternside Changs #1 fan\" on it. "
- icon = 'icons/obj/toy.dmi'
- icon_state = "foamblade"
- item_state = "arm_blade"
- attack_verb = list("pricked", "absorbed", "gored")
- w_class = WEIGHT_CLASS_SMALL
- resistance_flags = FLAMMABLE
+/obj/item/toy/foamblade
+ name = "foam armblade"
+ desc = "it says \"Sternside Changs #1 fan\" on it. "
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "foamblade"
+ item_state = "arm_blade"
+ attack_verb = list("pricked", "absorbed", "gored")
+ w_class = WEIGHT_CLASS_SMALL
+ resistance_flags = FLAMMABLE
/*
* Toy/fake flash
@@ -1220,7 +1247,6 @@ obj/item/toy/cards/deck/syndicate/black
spawn(20)
cooldown = FALSE
return
- ..()
/obj/item/toy/owl
name = "owl action figure"
@@ -1382,6 +1408,7 @@ obj/item/toy/cards/deck/syndicate/black
name = "xenomorph action figure"
desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use."
w_class = WEIGHT_CLASS_SMALL
+ bubble_icon = "alien"
var/cooldown = 0
/obj/item/toy/toy_xeno/attack_self(mob/user)
@@ -1390,7 +1417,7 @@ obj/item/toy/cards/deck/syndicate/black
user.visible_message("[user] pulls back the string on [src].")
icon_state = "[initial(icon_state)]_used"
sleep(5)
- audible_message("[bicon(src)] Hiss!")
+ atom_say("Hiss!")
var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg')
playsound(get_turf(src), pick(possible_sounds), 50, 1)
spawn(45)
diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm
index 7cf48095e72..8508c741524 100644
--- a/code/game/objects/items/trash.dm
+++ b/code/game/objects/items/trash.dm
@@ -8,6 +8,13 @@
desc = "This is rubbish."
resistance_flags = FLAMMABLE
+/obj/item/trash/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["metal"] += 2
+ C.stored_comms["wood"] += 1
+ C.stored_comms["glass"] += 1
+ qdel(src)
+ return TRUE
+
/obj/item/trash/raisins
name = "4no raisins"
icon_state= "4no_raisins"
diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm
index 7e965fdb283..1e34561c441 100755
--- a/code/game/objects/items/weapons/AI_modules.dm
+++ b/code/game/objects/items/weapons/AI_modules.dm
@@ -143,9 +143,8 @@ AI MODULES
target.set_zeroth_law(law)
GLOB.lawchanges.Add("The law specified [targetName]")
else
- to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite
-
- to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]")
+ to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite
+ to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]")
GLOB.lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overridden.")
/******************** ProtectStation ********************/
@@ -222,11 +221,11 @@ AI MODULES
log_law_changes(target, sender)
if(!is_special_character(target))
- target.set_zeroth_law("")
+ target.clear_zeroth_law()
target.laws.clear_supplied_laws()
target.laws.clear_ion_laws()
- to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.")
+ to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.")
target.show_laws()
/******************** Purge ********************/
@@ -238,8 +237,8 @@ AI MODULES
/obj/item/aiModule/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
..()
if(!is_special_character(target))
- target.set_zeroth_law("")
- to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.")
+ target.clear_zeroth_law()
+ to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.")
target.clear_supplied_laws()
target.clear_ion_laws()
target.clear_inherent_laws()
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index d6397025424..f8f9a48102a 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -477,9 +477,7 @@ GLOBAL_LIST_INIT(rcd_door_types, list(
return R.cell.charge >= (amount * use_multiplier)
/obj/item/rcd/proc/detonate_pulse()
- audible_message("[src] begins to vibrate and \
- buzz loudly!","[src] begins \
- vibrating violently!")
+ audible_message("[src] begins to vibrate and buzz loudly!", "[src] begins vibrating violently!")
// 5 seconds to get rid of it
addtimer(CALLBACK(src, .proc/detonate_pulse_explode), 50)
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index a8da7503c72..26cef27a0b4 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -58,7 +58,7 @@ RSF
if(!proximity) return
if(!(istype(A, /obj/structure/table) || istype(A, /turf/simulated/floor)))
return
- var spawn_location
+ var/spawn_location
var/turf/T = get_turf(A)
if(istype(T) && !T.density)
spawn_location = T
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 405ce47a033..dc26b14e24b 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -356,13 +356,13 @@
/obj/item/card/id/syndicate/attack_self(mob/user as mob)
if(!src.registered_name)
- var t = reject_bad_name(input(user, "What name would you like to use on this card?", "Agent Card name", ishuman(user) ? user.real_name : user.name))
+ var/t = reject_bad_name(input(user, "What name would you like to use on this card?", "Agent Card name", ishuman(user) ? user.real_name : user.name))
if(!t)
to_chat(user, "Invalid name.")
return
src.registered_name = t
- var u = sanitize(stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than maintenance.", "Agent Card Job Assignment", "Agent", MAX_MESSAGE_LEN))
+ var/u = sanitize(stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than maintenance.", "Agent Card Job Assignment", "Agent", MAX_MESSAGE_LEN))
if(!u)
to_chat(user, "Invalid assignment.")
src.registered_name = ""
diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm
index 91bb84f880b..1dc0b22abdf 100644
--- a/code/game/objects/items/weapons/chrono_eraser.dm
+++ b/code/game/objects/items/weapons/chrono_eraser.dm
@@ -32,7 +32,7 @@
if(PA)
qdel(PA)
else
- PA = new(src)
+ PA = new(user, src)
user.put_in_hands(PA)
/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user)
@@ -55,7 +55,7 @@
var/obj/structure/chrono_field/field = null
var/turf/startpos = null
-/obj/item/gun/energy/chrono_gun/New(var/obj/item/chrono_eraser/T)
+/obj/item/gun/energy/chrono_gun/Initialize(mapload, obj/item/chrono_eraser/T)
. = ..()
if(istype(T))
TED = T
@@ -188,7 +188,7 @@
/obj/structure/chrono_field/update_icon()
var/ttk_frame = 1 - (tickstokill / initial(tickstokill))
- ttk_frame = Clamp(Ceiling(ttk_frame * CHRONO_FRAME_COUNT), 1, CHRONO_FRAME_COUNT)
+ ttk_frame = clamp(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
if(ttk_frame != RPpos)
RPpos = ttk_frame
mob_underlay.icon_state = "frame[RPpos]"
diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm
index 24c904bc9d3..30ad91beffa 100644
--- a/code/game/objects/items/weapons/cigs.dm
+++ b/code/game/objects/items/weapons/cigs.dm
@@ -31,6 +31,7 @@ LIGHTERS ARE IN LIGHTERS.DM
var/smoketime = 150
var/chem_volume = 60
var/list/list_reagents = list("nicotine" = 40)
+ var/first_puff = TRUE // the first puff is a bit more reagents ingested
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
@@ -194,8 +195,9 @@ LIGHTERS ARE IN LIGHTERS.DM
if(reagents && reagents.total_volume) // check if it has any reagents at all
if(is_being_smoked) // if it's being smoked, transfer reagents to the mob
var/mob/living/carbon/C = loc
- for (var/datum/reagent/R in reagents.reagent_list)
- reagents.trans_id_to(C, R.id, max(REAGENTS_METABOLISM / reagents.reagent_list.len, 0.1)) //transfer at least .1 of each chem
+ for(var/datum/reagent/R in reagents.reagent_list)
+ reagents.trans_id_to(C, R.id, first_puff ? 1 : max(REAGENTS_METABOLISM / reagents.reagent_list.len, 0.1)) //transfer at least .1 of each chem
+ first_puff = FALSE
if(!reagents.total_volume) // There were reagents, but now they're gone
to_chat(C, "Your [name] loses its flavor.")
else // else just remove some of the reagents
@@ -309,6 +311,11 @@ LIGHTERS ARE IN LIGHTERS.DM
pixel_y = rand(-10,10)
transform = turn(transform,rand(0,360))
+/obj/item/cigbutt/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["wood"] += 1
+ qdel(src)
+ return TRUE
+
/obj/item/cigbutt/cigarbutt
name = "cigar butt"
desc = "A manky old cigar butt."
@@ -360,7 +367,7 @@ LIGHTERS ARE IN LIGHTERS.DM
lit = FALSE
icon_state = icon_off
item_state = icon_off
- M.update_inv_wear_mask(0)
+ M.update_inv_wear_mask()
STOP_PROCESSING(SSobj, src)
return
smoke()
@@ -377,6 +384,7 @@ LIGHTERS ARE IN LIGHTERS.DM
to_chat(user, "You refill the pipe with tobacco.")
reagents.add_reagent("nicotine", chem_volume)
smoketime = initial(smoketime)
+ first_puff = TRUE
/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/reagent_containers))
diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm
index 8815ad6a20f..42f65141094 100644
--- a/code/game/objects/items/weapons/cosmetics.dm
+++ b/code/game/objects/items/weapons/cosmetics.dm
@@ -5,16 +5,22 @@
icon_state = "lipstick"
w_class = WEIGHT_CLASS_TINY
var/colour = "red"
- var/open = 0
- var/list/lipstick_colors = list(
- "purple" = "purple",
- "jade" = "#216F43",
- "lime" = "lime",
- "black" = "black",
- "green" = "green",
- "blue" = "blue",
- "white" = "white")
+ var/open = FALSE
+ var/static/list/lipstick_colors
+/obj/item/lipstick/Initialize(mapload)
+ . = ..()
+ if(!lipstick_colors)
+ lipstick_colors = list(
+ "black" = "#000000",
+ "white" = "#FFFFFF",
+ "red" = "#FF0000",
+ "green" = "#00C000",
+ "blue" = "#0000FF",
+ "purple" = "#D55CD0",
+ "jade" = "#216F43",
+ "lime" = "#00FF00",
+ )
/obj/item/lipstick/purple
name = "purple lipstick"
@@ -22,7 +28,7 @@
/obj/item/lipstick/jade
name = "jade lipstick"
- colour = "#216F43"
+ colour = "jade"
/obj/item/lipstick/lime
name = "lime lipstick"
@@ -47,40 +53,38 @@
/obj/item/lipstick/random
name = "lipstick"
-/obj/item/lipstick/random/New()
- ..()
- var/lscolor = pick(lipstick_colors)//A random color is picked from the var defined initially in a new var.
- colour = lipstick_colors[lscolor]//The color of the lipstick is pulled from the new variable (right hand side, HTML & Hex RGB)
- name = "[lscolor] lipstick"//The new variable is also used to match the name to the color of the lipstick. Kudos to Desolate & Lemon
+/obj/item/lipstick/random/Initialize(mapload)
+ . = ..()
+ var/lscolor = pick(lipstick_colors) // A random color is picked from the var defined initially in a new var.
+ colour = lipstick_colors[lscolor] // The color of the lipstick is pulled from the new variable (right hand side, HTML & Hex RGB)
+ name = "[lscolor] lipstick" // The new variable is also used to match the name to the color of the lipstick. Kudos to Desolate & Lemon
-
-/obj/item/lipstick/attack_self(mob/user as mob)
- overlays.Cut()
+/obj/item/lipstick/attack_self(mob/user)
+ cut_overlays()
to_chat(user, "You twist \the [src] [open ? "closed" : "open"].")
open = !open
if(open)
- var/image/colored = image("icon"='icons/obj/items.dmi', "icon_state"="lipstick_uncap_color")
- colored.color = colour
+ var/image/colored = mutable_appearance('icons/obj/items.dmi', "lipstick_uncap_color")
+ colored.color = lipstick_colors[colour]
icon_state = "lipstick_uncap"
- overlays += colored
+ add_overlay(colored)
else
icon_state = "lipstick"
-/obj/item/lipstick/attack(mob/M as mob, mob/user as mob)
- if(!open) return
-
- if(!istype(M, /mob)) return
+/obj/item/lipstick/attack(mob/M, mob/user)
+ if(!open || !istype(M))
+ return
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(H.lip_style) //if they already have lipstick on
+ if(H.lip_style) // If they already have lipstick on
to_chat(user, "You need to wipe off the old lipstick first!")
return
if(H == user)
user.visible_message("[user] does [user.p_their()] lips with [src].", \
"You take a moment to apply [src]. Perfect!")
H.lip_style = "lipstick"
- H.lip_color = colour
+ H.lip_color = lipstick_colors[colour]
H.update_body()
else
user.visible_message("[user] begins to do [H]'s lips with \the [src].", \
@@ -89,7 +93,7 @@
user.visible_message("[user] does [H]'s lips with \the [src].", \
"You apply \the [src].")
H.lip_style = "lipstick"
- H.lip_color = colour
+ H.lip_color = lipstick_colors[colour]
H.update_body()
else
to_chat(user, "Where are the lips on that?")
diff --git a/code/game/objects/items/weapons/courtroom.dm b/code/game/objects/items/weapons/courtroom.dm
index 09d43434560..4a9e3c2b7cf 100644
--- a/code/game/objects/items/weapons/courtroom.dm
+++ b/code/game/objects/items/weapons/courtroom.dm
@@ -27,10 +27,12 @@
throwforce = 2.0
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
+ var/next_gavel_hit
/obj/item/gavelblock/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/gavelhammer))
- playsound(loc, 'sound/items/gavel.ogg', 100, 1)
- user.visible_message("[user] strikes \the [src] with \the [I].")
- else
+ if(!istype(I, /obj/item/gavelhammer))
return
+ if(world.time > next_gavel_hit)
+ playsound(loc, 'sound/items/gavel.ogg', 100, 1)
+ next_gavel_hit = world.time + 5 SECONDS
+ user.visible_message("[user] strikes \the [src] with \the [I].")
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 581c4395650..ee98d309876 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -72,7 +72,7 @@
if(powered) //so it doesn't show charge if it's unpowered
if(cell)
var/ratio = cell.charge / cell.maxcharge
- ratio = Ceiling(ratio*4) * 25
+ ratio = CEILING(ratio*4, 1) * 25
overlays += "[icon_state]-charge[ratio]"
/obj/item/defibrillator/CheckParts(list/parts_list)
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index bc6a98a9b1f..629942860be 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -138,7 +138,7 @@
/obj/item/dice/proc/diceroll(mob/user)
result = roll(sides)
if(rigged != DICE_NOT_RIGGED && result != rigged_value)
- if(rigged == DICE_BASICALLY_RIGGED && prob(Clamp(1/(sides - 1) * 100, 25, 80)))
+ if(rigged == DICE_BASICALLY_RIGGED && prob(clamp(1/(sides - 1) * 100, 25, 80)))
result = rigged_value
else if(rigged == DICE_TOTALLY_RIGGED)
result = rigged_value
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 8f11f65fe71..45047e97156 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -147,10 +147,6 @@
to_chat(user, "You inject yourself with [src].")
add_attack_logs(user, M, attack_log, ATKLOG_ALL)
- if(!iscarbon(user))
- M.LAssailant = null
- else
- M.LAssailant = user
inject(M, user)
used = TRUE
diff --git a/code/game/objects/items/weapons/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm
index c2dc8e285ab..1dcc4a942c2 100644
--- a/code/game/objects/items/weapons/dnascrambler.dm
+++ b/code/game/objects/items/weapons/dnascrambler.dm
@@ -45,7 +45,7 @@
scramble(1, H, 100)
H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species.
H.sync_organ_dna(assimilate = 1)
- H.update_body(0)
+ H.update_body()
H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover.
H.reset_markings() //...Or markings.
H.dna.ResetUIFrom(H)
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 5c69a59aba9..9584130c0c6 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -62,7 +62,7 @@
return
var/newtime = input(usr, "Please set the timer.", "Timer", det_time) as num
if(user.is_in_active_hand(src))
- newtime = Clamp(newtime, 10, 60000)
+ newtime = clamp(newtime, 10, 60000)
det_time = newtime
to_chat(user, "Timer set for [det_time] seconds.")
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 5a3286bfc05..48edcc826e6 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -49,8 +49,7 @@
to_chat(user, "You cut open the present.")
for(var/mob/M in src) //Should only be one but whatever.
- M.loc = src.loc
- M.reset_perspective(null)
+ M.forceMove(loc)
qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm
index cfb2e1cad3d..1dcf250dfe4 100644
--- a/code/game/objects/items/weapons/grenades/clowngrenade.dm
+++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm
@@ -13,22 +13,12 @@
/obj/item/grenade/clown_grenade/prime()
..()
playsound(src.loc, 'sound/items/bikehorn.ogg', 25, -3)
- /*
- for(var/turf/simulated/floor/T in view(affected_area, src.loc))
- if(prob(75))
- banana(T)
- */
var/i = 0
var/number = 0
for(var/direction in GLOB.alldirs)
for(i = 0; i < 2; i++)
number++
var/obj/item/grown/bananapeel/traitorpeel/peel = new /obj/item/grown/bananapeel/traitorpeel(get_turf(src.loc))
- /* var/direction = pick(alldirs)
- var/spaces = pick(1;150, 2)
- var/a = 0
- for(a = 0; a < spaces; a++)
- step(peel,direction)*/
var/a = 1
if(number & 2)
for(a = 1; a <= 2; a++)
@@ -39,21 +29,17 @@
qdel(src)
return
-/obj/item/grown/bananapeel/traitorpeel
- trip_stun = 0
- trip_weaken = 7
- trip_tiles = 4
- trip_walksafe = FALSE
-
- trip_chance = 100
-
-
-/obj/item/grown/bananapeel/traitorpeel/on_trip(mob/living/carbon/human/H)
+/obj/item/grown/bananapeel/traitorpeel/New(newloc, obj/item/seeds/new_seed)
. = ..()
- if(.)
- to_chat(H, "Your feet feel like they're on fire!")
- H.take_overall_damage(0, rand(2,8))
- H.take_organ_damage(2) // Was 5 -- TLE
+ // The reason this AddComponent is here and not in ComponentInitialize() is because if it's put there, it will be ran before the parent New proc for /grown types.
+ // And then be overriden by the generic component placed onto it by the `/datum/plant_gene/trait/slip`.
+ AddComponent(/datum/component/slippery, src, 0, 7, 100, 4, FALSE)
+
+/obj/item/grown/bananapeel/traitorpeel/after_slip(mob/living/carbon/human/H)
+ to_chat(H, "Your feet feel like they're on fire!")
+ H.take_overall_damage(0, rand(2,8))
+ H.take_organ_damage(2)
+ return ..()
/obj/item/grown/bananapeel/traitorpeel/throw_impact(atom/hit_atom)
var/burned = rand(1,3)
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index e188279eb8c..1f73e5c7062 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -37,6 +37,9 @@
cuff(C, user)
/obj/item/restraints/handcuffs/proc/cuff(mob/living/carbon/C, mob/user, remove_src = TRUE)
+ if(!istype(C)) // Shouldn't be able to cuff anything but carbons.
+ return
+
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(!(H.has_left_hand() || H.has_right_hand()))
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index 4efb6994e8d..6423bbeb6ff 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -488,7 +488,7 @@
var/mob/living/carbon/human/holder = loc
if(src == holder.l_hand || src == holder.r_hand) // Holding this in your hand will
for(var/mob/living/carbon/human/H in range(5, loc))
- if(H.mind.vampire && !H.mind.vampire.get_ability(/datum/vampire_passive/full))
+ if(H.mind && H.mind.vampire && !H.mind.vampire.get_ability(/datum/vampire_passive/full))
H.mind.vampire.nullified = max(5, H.mind.vampire.nullified + 2)
if(prob(10))
to_chat(H, "Being in the presence of [holder]'s [src] is interfering with your powers!")
diff --git a/code/game/objects/items/weapons/implants/implant_storage.dm b/code/game/objects/items/weapons/implants/implant_storage.dm
index 18b08bba283..b530fd860fa 100644
--- a/code/game/objects/items/weapons/implants/implant_storage.dm
+++ b/code/game/objects/items/weapons/implants/implant_storage.dm
@@ -20,6 +20,10 @@
..()
storage = new /obj/item/storage/hidden/implant(src)
+/obj/item/implant/storage/emp_act(severity)
+ ..()
+ storage.emp_act(severity)
+
/obj/item/implant/storage/activate()
storage.MouseDrop(imp_in)
diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm
index 05d2363ee01..40998caa774 100644
--- a/code/game/objects/items/weapons/implants/implant_traitor.dm
+++ b/code/game/objects/items/weapons/implants/implant_traitor.dm
@@ -40,14 +40,13 @@
L.adjustBrainLoss(20)
removed(mindslave_target)
qdel(src)
- return -1
+ return -1
if(ismindshielded(mindslave_target))
mindslave_target.visible_message("[mindslave_target] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.")
removed(mindslave_target)
qdel(src)
return -1
- mindslave_target.implanting = 1
to_chat(mindslave_target, "You feel completely loyal to [user.name].")
if(!(user.mind in SSticker.mode.implanter))
SSticker.mode.implanter[user.mind] = list()
@@ -56,7 +55,7 @@
SSticker.mode.implanted.Add(mindslave_target.mind)
SSticker.mode.implanted[mindslave_target.mind] = user.mind
SSticker.mode.implanter[user.mind] = implanters
-
+
to_chat(mindslave_target, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.")
var/datum/objective/protect/mindslave/MS = new
diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm
index e24346c1ee9..1bfeeabae03 100644
--- a/code/game/objects/items/weapons/lighters.dm
+++ b/code/game/objects/items/weapons/lighters.dm
@@ -1,29 +1,19 @@
-/////////
-//ZIPPO//
-/////////
+// Basic lighters
/obj/item/lighter
name = "cheap lighter"
desc = "A cheap-as-free lighter."
icon = 'icons/obj/items.dmi'
icon_state = "lighter-g"
item_state = "lighter-g"
- var/icon_on = "lighter-g-on"
- var/icon_off = "lighter-g"
w_class = WEIGHT_CLASS_TINY
throwforce = 4
flags = CONDUCT
slot_flags = SLOT_BELT
attack_verb = null
resistance_flags = FIRE_PROOF
- var/lit = 0
-
-/obj/item/lighter/zippo
- name = "zippo lighter"
- desc = "The zippo."
- icon_state = "zippo"
- item_state = "zippo"
- icon_on = "zippoon"
- icon_off = "zippo"
+ var/lit = FALSE
+ var/icon_on = "lighter-g-on"
+ var/icon_off = "lighter-g"
/obj/item/lighter/random/New()
..()
@@ -33,54 +23,51 @@
icon_state = icon_off
/obj/item/lighter/attack_self(mob/living/user)
- if(user.r_hand == src || user.l_hand == src || isrobot(user))
- if(!lit)
- lit = 1
- w_class = WEIGHT_CLASS_BULKY
- icon_state = icon_on
- item_state = icon_on
- force = 5
- damtype = "fire"
- hitsound = 'sound/items/welder.ogg'
- attack_verb = list("burnt", "singed")
- if(istype(src, /obj/item/lighter/zippo) )
- user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.")
- playsound(src.loc, 'sound/items/zippolight.ogg', 25, 1)
- else
- if(prob(75))
- user.visible_message("After a few attempts, [user] manages to light the [src].")
- else
- to_chat(user, "You burn yourself while lighting the lighter.")
- var/mob/living/M = user
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
- if(affecting.receive_damage( 0, 5 )) //INFERNO
- H.UpdateDamageIcon()
- user.visible_message("After a few attempts, [user] manages to light the [src], [user.p_they()] however burn[user.p_s()] [user.p_their()] finger in the process.")
-
- set_light(2)
- START_PROCESSING(SSobj, src)
- else
- lit = 0
- w_class = WEIGHT_CLASS_TINY
- icon_state = icon_off
- item_state = icon_off
- hitsound = "swing_hit"
- force = 0
- attack_verb = null //human_defense.dm takes care of it
- if(istype(src, /obj/item/lighter/zippo) )
- user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.")
- playsound(src.loc, 'sound/items/zippoclose.ogg', 25, 1)
- else
- user.visible_message("[user] quietly shuts off the [src].")
-
- set_light(0)
- STOP_PROCESSING(SSobj, src)
+ . = ..()
+ if(!lit)
+ turn_on_lighter(user)
else
- return ..()
- return
+ turn_off_lighter(user)
+/obj/item/lighter/proc/turn_on_lighter(mob/living/user)
+ lit = TRUE
+ w_class = WEIGHT_CLASS_BULKY
+ icon_state = icon_on
+ item_state = icon_on
+ force = 5
+ damtype = BURN
+ hitsound = 'sound/items/welder.ogg'
+ attack_verb = list("burnt", "singed")
+
+ attempt_light(user)
+ set_light(2)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/lighter/proc/attempt_light(mob/living/user)
+ if(prob(75) || issilicon(user)) // Robots can never burn themselves trying to light it.
+ to_chat(user, "You light [src].")
+ else
+ var/mob/living/carbon/human/H = user
+ var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
+ if(affecting.receive_damage( 0, 5 )) //INFERNO
+ H.UpdateDamageIcon()
+ to_chat(user,"You light [src], but you burn your hand in the process.")
+
+/obj/item/lighter/proc/turn_off_lighter(mob/living/user)
+ lit = FALSE
+ w_class = WEIGHT_CLASS_TINY
+ icon_state = icon_off
+ item_state = icon_off
+ hitsound = "swing_hit"
+ force = 0
+ attack_verb = null //human_defense.dm takes care of it
+
+ show_off_message(user)
+ set_light(0)
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/lighter/proc/show_off_message(mob/living/user)
+ to_chat(user, "You shut off [src].")
/obj/item/lighter/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
if(!isliving(M))
@@ -108,6 +95,41 @@
location.hotspot_expose(700, 5)
return
+// Zippo lighters
+/obj/item/lighter/zippo
+ name = "zippo lighter"
+ desc = "The zippo."
+ icon_state = "zippo"
+ item_state = "zippo"
+ icon_on = "zippoon"
+ icon_off = "zippo"
+ var/next_on_message
+ var/next_off_message
+
+/obj/item/lighter/zippo/turn_on_lighter(mob/living/user)
+ . = ..()
+ if(world.time > next_on_message)
+ user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.")
+ playsound(src.loc, 'sound/items/zippolight.ogg', 25, 1)
+ next_on_message = world.time + 5 SECONDS
+ else
+ to_chat(user, "You light [src].")
+
+/obj/item/lighter/zippo/turn_off_lighter(mob/living/user)
+ . = ..()
+ if(world.time > next_off_message)
+ user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.")
+ playsound(src.loc, 'sound/items/zippoclose.ogg', 25, 1)
+ next_off_message = world.time + 5 SECONDS
+ else
+ to_chat(user, "You shut off [src].")
+
+/obj/item/lighter/zippo/show_off_message(mob/living/user)
+ return
+
+/obj/item/lighter/zippo/attempt_light(mob/living/user)
+ return
+
//EXTRA LIGHTERS
/obj/item/lighter/zippo/nt_rep
name = "gold engraved zippo"
@@ -222,12 +244,18 @@
else
..()
+/obj/item/match/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(burnt)
+ C.stored_comms["wood"] += 1
+ qdel(src)
+ return TRUE
+ return ..()
+
/obj/item/proc/help_light_cig(mob/living/M)
var/mask_item = M.get_item_by_slot(slot_wear_mask)
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
return mask_item
-
/obj/item/match/firebrand
name = "firebrand"
desc = "An unlit firebrand. It makes you wonder why it's not just called a stick."
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index d91bb29ff76..bab2ff02fbb 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -5,6 +5,7 @@
icon = 'icons/obj/library.dmi'
due_date = 0 // Game time in 1/10th seconds
unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified
+ has_drm = TRUE // No reuploading. Piracy is a crime
/obj/item/book/manual/engineering_construction
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index c3f2e50174b..f6fb213b353 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -6,7 +6,7 @@
var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects
w_class = WEIGHT_CLASS_SMALL
var/w_class_on = WEIGHT_CLASS_BULKY
- var/icon_state_on = "axe1"
+ var/icon_state_on
var/list/attack_verb_on = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/blade1.ogg' // Probably more appropriate than the previous hitsound. -- Dave
usesound = 'sound/weapons/blade1.ogg'
@@ -37,7 +37,7 @@
return BRUTELOSS|FIRELOSS
/obj/item/melee/energy/attack_self(mob/living/carbon/user)
- if(user.disabilities & CLUMSY && prob(50))
+ if((CLUMSY in user.mutations) && prob(50))
to_chat(user, "You accidentally cut yourself with [src], like a doofus!")
user.take_organ_damage(5,5)
active = !active
@@ -48,9 +48,9 @@
throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
- if(!item_color)
+ if(icon_state_on)
icon_state = icon_state_on
- set_light(brightness_on)
+ set_light(brightness_on, l_color = item_color ? colormap[item_color] : null)
else
icon_state = "sword[item_color]"
set_light(brightness_on, l_color=colormap[item_color])
@@ -80,6 +80,7 @@
name = "energy axe"
desc = "An energised battle axe."
icon_state = "axe0"
+ icon_state_on = "axe1"
force = 40
force_on = 150
throwforce = 25
@@ -290,7 +291,7 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
- if(H.disabilities & CLUMSY && prob(50))
+ if((CLUMSY in H.mutations) && prob(50))
to_chat(H, "You accidentally cut yourself with [src], like a doofus!")
H.take_organ_damage(10,10)
active = !active
@@ -301,9 +302,9 @@
throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
- if(!item_color)
+ if(icon_state_on)
icon_state = icon_state_on
- set_light(brightness_on)
+ set_light(brightness_on, l_color = item_color ? colormap[item_color] : null)
else
icon_state = "sword[item_color]"
set_light(brightness_on, l_color=colormap[item_color])
diff --git a/code/game/objects/items/weapons/misc.dm b/code/game/objects/items/weapons/misc.dm
index 0732c0fdd1d..40d68cc8fc6 100644
--- a/code/game/objects/items/weapons/misc.dm
+++ b/code/game/objects/items/weapons/misc.dm
@@ -77,6 +77,10 @@
item_state = "gift"
w_class = WEIGHT_CLASS_BULKY
+/obj/item/gift/emp_act(severity)
+ ..()
+ gift.emp_act(severity)
+
/obj/item/kidanglobe
name = "Kidan homeworld globe"
icon = 'icons/obj/decorations.dmi'
diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm
index be901e51ef2..415a02f4456 100644
--- a/code/game/objects/items/weapons/rpd.dm
+++ b/code/game/objects/items/weapons/rpd.dm
@@ -106,7 +106,7 @@
P = new(T, whatpipe, iconrotation) //Make the pipe, BUT WAIT! There's more!
if(!iconrotation && P.is_bent_pipe()) //Automatically rotates dispensed pipes if the user selected auto-rotation
P.dir = turn(user.dir, 135)
- else if(!iconrotation && P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT)) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction
+ else if(!iconrotation && (P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT))) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction
P.dir = turn(user.dir, -180)
else if(iconrotation && P.is_bent_pipe()) //If user selected a rotation and the pipe is bent
P.dir = turn(iconrotation, -45)
diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm
index 28d7df5874f..14f3b0ab91f 100644
--- a/code/game/objects/items/weapons/scrolls.dm
+++ b/code/game/objects/items/weapons/scrolls.dm
@@ -60,7 +60,7 @@
return
if(thearea.tele_proof && !istype(thearea, /area/wizard_station))
- to_chat(user, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.")
+ to_chat(user, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.")
return
var/datum/effect_system/smoke_spread/smoke = new
@@ -79,7 +79,7 @@
L+=T
if(!L.len)
- to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.")
+ to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.")
return
if(user && user.buckled)
@@ -100,7 +100,8 @@
break
if(!success)
- user.loc = pick(L)
+ user.forceMove(pick(L))
smoke.start()
src.uses -= 1
+ user.update_action_buttons_icon() //Update action buttons as some spells might now be castable
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index 52c2aea5ddb..6daabffe000 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -88,6 +88,11 @@
playsound(loc, 'sound/effects/glass_step.ogg', 50, TRUE)
return ..()
+/obj/item/shard/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["glass"] += 3
+ qdel(src)
+ return TRUE
+
/obj/item/shard/plasma
name = "plasma shard"
desc = "A shard of plasma glass. Considerably tougher then normal glass shards. Apparently not tough enough to be a window."
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index 362ab601685..19e56e161e3 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -76,7 +76,7 @@
return (active)
/obj/item/shield/energy/attack_self(mob/living/carbon/human/user)
- if(user.disabilities & CLUMSY && prob(50))
+ if((CLUMSY in user.mutations) && prob(50))
to_chat(user, "You beat yourself in the head with [src].")
user.take_organ_damage(5)
active = !active
diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm
index 62f65b5a6cc..cb220ff9565 100644
--- a/code/game/objects/items/weapons/soap.dm
+++ b/code/game/objects/items/weapons/soap.dm
@@ -11,15 +11,11 @@
throw_speed = 4
throw_range = 20
discrete = 1
-
- trip_stun = 4
- trip_weaken = 2
- trip_chance = 100
- trip_walksafe = FALSE
- trip_verb = TV_SLIP
-
var/cleanspeed = 50 //slower than mop
+/obj/item/soap/ComponentInitialize()
+ AddComponent(/datum/component/slippery, src, 4, 2, 100, 0, FALSE)
+
/obj/item/soap/afterattack(atom/target, mob/user, proximity)
if(!proximity) return
//I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing.
diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm
index 1cc2b25edf0..0d5591bbc16 100644
--- a/code/game/objects/items/weapons/stock_parts.dm
+++ b/code/game/objects/items/weapons/stock_parts.dm
@@ -235,57 +235,6 @@
rating = 4
materials = list(MAT_METAL=80)
-// Subspace stock parts
-
-/obj/item/stock_parts/subspace/ansible
- name = "subspace ansible"
- icon_state = "subspace_ansible"
- desc = "A compact module capable of sensing extradimensional activity."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=1"
- materials = list(MAT_METAL=30, MAT_GLASS=10)
-
-/obj/item/stock_parts/subspace/filter
- name = "hyperwave filter"
- icon_state = "hyperwave_filter"
- desc = "A tiny device capable of filtering and converting super-intense radiowaves."
- origin_tech = "programming=2;magnets=2"
- materials = list(MAT_METAL=30, MAT_GLASS=10)
-
-/obj/item/stock_parts/subspace/amplifier
- name = "subspace amplifier"
- icon_state = "subspace_amplifier"
- desc = "A compact micro-machine capable of amplifying weak subspace transmissions."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
- materials = list(MAT_METAL=30, MAT_GLASS=10)
-
-/obj/item/stock_parts/subspace/treatment
- name = "subspace treatment disk"
- icon_state = "treatment_disk"
- desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
- materials = list(MAT_METAL=30, MAT_GLASS=10)
-
-/obj/item/stock_parts/subspace/analyzer
- name = "subspace wavelength analyzer"
- icon_state = "wavelength_analyzer"
- desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
- materials = list(MAT_METAL=30, MAT_GLASS=10)
-
-/obj/item/stock_parts/subspace/crystal
- name = "ansible crystal"
- icon_state = "ansible_crystal"
- desc = "A crystal made from pure glass used to transmit laser databursts to subspace."
- origin_tech = "magnets=2;materials=2;bluespace=2;plasmatech=2"
- materials = list(MAT_GLASS=50)
-
-/obj/item/stock_parts/subspace/transmitter
- name = "subspace transmitter"
- icon_state = "subspace_transmitter"
- desc = "A large piece of equipment used to open a window into the subspace dimension."
- origin_tech = "magnets=2;materials=2;bluespace=2"
- materials = list(MAT_METAL=50)
-
/obj/item/research//Makes testing much less of a pain -Sieve
name = "research"
icon = 'icons/obj/stock_parts.dmi'
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 757d2b05757..26045731bd9 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -230,6 +230,11 @@
desc = "An NT Deluxe satchel, with the finest quality leather and the company logo in a thin gold stitch"
icon_state = "nt_deluxe"
+/obj/item/storage/backpack/satchel/lizard
+ name = "lizard skin handbag"
+ desc = "A handbag made out of what appears to be supple green Unathi skin. A face can be vaguely seen on the front."
+ icon_state = "satchel-lizard"
+
/obj/item/storage/backpack/satchel/withwallet/New()
..()
new /obj/item/storage/wallet/random(src)
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index 66288713775..6d5a192c641 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -33,9 +33,11 @@
icon_state = "trashbag"
item_state = "trashbag"
- w_class = WEIGHT_CLASS_TINY
+ w_class = WEIGHT_CLASS_BULKY
max_w_class = WEIGHT_CLASS_SMALL
+ slot_flags = null
storage_slots = 30
+ max_combined_w_class = 30
can_hold = list() // any
cant_hold = list(/obj/item/disk/nuclear)
@@ -45,18 +47,15 @@
return TOXLOSS
/obj/item/storage/bag/trash/update_icon()
- if(contents.len == 0)
- w_class = WEIGHT_CLASS_TINY
- icon_state = "[initial(icon_state)]"
- else if(contents.len < 12)
- w_class = WEIGHT_CLASS_BULKY
- icon_state = "[initial(icon_state)]1"
- else if(contents.len < 21)
- w_class = WEIGHT_CLASS_BULKY
- icon_state = "[initial(icon_state)]2"
- else
- w_class = WEIGHT_CLASS_BULKY
- icon_state = "[initial(icon_state)]3"
+ switch(contents.len)
+ if(20 to INFINITY)
+ icon_state = "[initial(icon_state)]3"
+ if(11 to 20)
+ icon_state = "[initial(icon_state)]2"
+ if(1 to 11)
+ icon_state = "[initial(icon_state)]1"
+ else
+ icon_state = "[initial(icon_state)]"
/obj/item/storage/bag/trash/cyborg
@@ -422,13 +421,13 @@
/obj/item/storage/bag/tray/cyborg/afterattack(atom/target, mob/user as mob)
if( isturf(target) || istype(target,/obj/structure/table) )
- var foundtable = istype(target,/obj/structure/table/)
+ var/foundtable = istype(target,/obj/structure/table/)
if( !foundtable ) //it must be a turf!
for(var/obj/structure/table/T in target)
foundtable = 1
break
- var turf/dropspot
+ var/turf/dropspot
if( !foundtable ) // don't unload things onto walls or other silly places.
dropspot = user.loc
else if( isturf(target) ) // they clicked on a turf with a table in it
@@ -438,7 +437,7 @@
overlays = null
- var droppedSomething = 0
+ var/droppedSomething = 0
for(var/obj/item/I in contents)
I.loc = dropspot
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 755b0076c3c..403088e2b71 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -134,7 +134,8 @@
/obj/item/rad_laser,
/obj/item/sensor_device,
/obj/item/wrench/medical,
- /obj/item/handheld_defibrillator
+ /obj/item/handheld_defibrillator,
+ /obj/item/reagent_containers/applicator
)
/obj/item/storage/belt/medical/surgery
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 97a99491e0a..da0094bb2ef 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -1124,6 +1124,11 @@
playsound(loc, "rustle", 50, 1, -5)
user.visible_message("[user] hugs \the [src].","You hug \the [src].")
+/obj/item/storage/box/wizard
+ name = "magical box"
+ desc = "It's just an ordinary magical box."
+ icon_state = "box_wizard"
+
#undef NODESIGN
#undef NANOTRASEN
#undef SYNDI
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index f0ab5bd5ac7..37f568fa51a 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -215,6 +215,13 @@
//if we get this far, handle the insertion checks as normal
.=..()
+/obj/item/storage/fancy/cigarettes/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!length(contents))
+ C.stored_comms["wood"] += 1
+ qdel(src)
+ return TRUE
+ return ..()
+
/obj/item/storage/fancy/cigarettes/dromedaryco
name = "\improper DromedaryCo packet"
desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\""
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index a9da4a69241..4ff769a7d3f 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -14,7 +14,7 @@
icon_state = "firstaid"
throw_speed = 2
throw_range = 8
- var/empty = 0
+ var/empty = FALSE
req_one_access =list(ACCESS_MEDICAL, ACCESS_ROBOTICS) //Access and treatment are utilized for medbots.
var/treatment_brute = "salglu_solution"
var/treatment_oxy = "salbutamol"
@@ -33,39 +33,51 @@
item_state = "firstaid-ointment"
med_bot_skin = "ointment"
- New()
- ..()
- if(empty) return
-
- icon_state = pick("ointment","firefirstaid")
-
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/healthanalyzer( src )
- new /obj/item/reagent_containers/hypospray/autoinjector( src )
- new /obj/item/reagent_containers/food/pill/salicylic( src )
+/obj/item/storage/firstaid/fire/New()
+ ..()
+ if(empty)
return
+ icon_state = pick("ointment", "firefirstaid")
+ new /obj/item/reagent_containers/applicator/burn(src)
+ new /obj/item/reagent_containers/food/pill/patch/silver_sulf/small(src)
+ new /obj/item/healthanalyzer(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector(src)
+ new /obj/item/reagent_containers/food/pill/salicylic(src)
/obj/item/storage/firstaid/fire/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/regular
desc = "A general medical kit that contains medical patches for both brute damage and burn damage. Also contains an epinephrine syringe for emergency use and a health analyzer"
icon_state = "firstaid"
- New()
- ..()
- if(empty) return
- new /obj/item/reagent_containers/food/pill/patch/styptic( src )
- new /obj/item/reagent_containers/food/pill/patch/styptic( src )
- new /obj/item/reagent_containers/food/pill/salicylic( src )
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src )
- new /obj/item/healthanalyzer( src )
- new /obj/item/reagent_containers/hypospray/autoinjector( src )
+/obj/item/storage/firstaid/regular/New()
+ ..()
+ if(empty)
return
+ new /obj/item/reagent_containers/food/pill/patch/styptic(src)
+ new /obj/item/reagent_containers/food/pill/patch/styptic(src)
+ new /obj/item/reagent_containers/food/pill/salicylic(src)
+ new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src)
+ new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src)
+ new /obj/item/healthanalyzer(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector(src)
+
+/obj/item/storage/firstaid/doctor
+ desc = "A general medical kit that contains medical patches for both brute damage and burn damage. Also contains an epinephrine syringe for emergency use and a health analyzer"
+ icon_state = "firstaid"
+
+/obj/item/storage/firstaid/doctor/New()
+ ..()
+ if(empty)
+ return
+ new /obj/item/reagent_containers/applicator/brute(src)
+ new /obj/item/reagent_containers/applicator/burn(src)
+ new /obj/item/reagent_containers/food/pill/patch/styptic(src)
+ new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src)
+ new /obj/item/reagent_containers/food/pill/salicylic(src)
+ new /obj/item/healthanalyzer/advanced(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector(src)
/obj/item/storage/firstaid/toxin
name = "toxin first aid kit"
@@ -74,23 +86,21 @@
item_state = "firstaid-toxin"
med_bot_skin = "tox"
- New()
- ..()
- if(empty) return
-
- icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
-
- new /obj/item/reagent_containers/syringe/charcoal( src )
- new /obj/item/reagent_containers/syringe/charcoal( src )
- new /obj/item/reagent_containers/syringe/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/healthanalyzer( src )
+/obj/item/storage/firstaid/toxin/New()
+ ..()
+ if(empty)
return
+ icon_state = pick("antitoxin", "antitoxfirstaid", "antitoxfirstaid2", "antitoxfirstaid3")
+ new /obj/item/reagent_containers/syringe/charcoal(src)
+ new /obj/item/reagent_containers/syringe/charcoal(src)
+ new /obj/item/reagent_containers/syringe/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/healthanalyzer(src)
/obj/item/storage/firstaid/toxin/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/o2
name = "oxygen deprivation first aid kit"
@@ -99,18 +109,18 @@
item_state = "firstaid-o2"
med_bot_skin = "o2"
- New()
- ..()
- if(empty) return
- new /obj/item/reagent_containers/food/pill/salbutamol( src )
- new /obj/item/reagent_containers/food/pill/salbutamol( src )
- new /obj/item/reagent_containers/food/pill/salbutamol( src )
- new /obj/item/reagent_containers/food/pill/salbutamol( src )
- new /obj/item/healthanalyzer( src )
+/obj/item/storage/firstaid/o2/New()
+ ..()
+ if(empty)
return
+ new /obj/item/reagent_containers/food/pill/salbutamol(src)
+ new /obj/item/reagent_containers/food/pill/salbutamol(src)
+ new /obj/item/reagent_containers/food/pill/salbutamol(src)
+ new /obj/item/reagent_containers/food/pill/salbutamol(src)
+ new /obj/item/healthanalyzer(src)
/obj/item/storage/firstaid/o2/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/brute
name = "brute trauma treatment kit"
@@ -119,23 +129,19 @@
item_state = "firstaid-brute"
med_bot_skin = "brute"
- New()
- ..()
- if(empty) return
-
- icon_state = pick("brute","brute2")
-
- new /obj/item/reagent_containers/food/pill/patch/styptic(src)
- new /obj/item/reagent_containers/food/pill/patch/styptic(src)
- new /obj/item/reagent_containers/food/pill/patch/styptic(src)
- new /obj/item/reagent_containers/food/pill/patch/styptic(src)
- new /obj/item/healthanalyzer(src)
- new /obj/item/reagent_containers/hypospray/autoinjector(src)
- new /obj/item/stack/medical/bruise_pack(src)
+/obj/item/storage/firstaid/brute/New()
+ ..()
+ if(empty)
return
+ icon_state = pick("brute", "brute2")
+ new /obj/item/reagent_containers/applicator/brute(src)
+ new /obj/item/reagent_containers/food/pill/patch/styptic/small(src)
+ new /obj/item/healthanalyzer(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector(src)
+ new /obj/item/stack/medical/bruise_pack(src)
/obj/item/storage/firstaid/brute/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/adv
name = "advanced first-aid kit"
@@ -157,7 +163,7 @@
new /obj/item/healthanalyzer(src)
/obj/item/storage/firstaid/adv/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/machine
name = "machine repair kit"
@@ -178,7 +184,7 @@
new /obj/item/robotanalyzer(src)
/obj/item/storage/firstaid/machine/empty
- empty = 1
+ empty = TRUE
/obj/item/storage/firstaid/tactical
@@ -196,18 +202,15 @@
/obj/item/storage/firstaid/tactical/New()
..()
- if(empty) return
+ if(empty)
+ return
new /obj/item/reagent_containers/hypospray/combat(src)
- new /obj/item/reagent_containers/food/pill/patch/synthflesh(src) // Because you ain't got no time to look at what damage dey taking yo
- new /obj/item/reagent_containers/food/pill/patch/synthflesh(src)
- new /obj/item/reagent_containers/food/pill/patch/synthflesh(src)
- new /obj/item/reagent_containers/food/pill/patch/synthflesh(src)
+ new /obj/item/reagent_containers/applicator/dual(src) // Because you ain't got no time to look at what damage dey taking yo
new /obj/item/defibrillator/compact/combat/loaded(src)
new /obj/item/clothing/glasses/hud/health/night(src)
- return
/obj/item/storage/firstaid/tactical/empty
- empty =1
+ empty = TRUE
/obj/item/storage/firstaid/surgery
name = "field surgery kit"
@@ -347,15 +350,15 @@
desc = "Contains pills used to counter toxins."
wrapper_color = COLOR_GREEN
- New()
- ..()
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
- new /obj/item/reagent_containers/food/pill/charcoal( src )
+/obj/item/storage/pill_bottle/charcoal/New()
+ ..()
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
+ new /obj/item/reagent_containers/food/pill/charcoal(src)
/obj/item/storage/pill_bottle/painkillers
name = "Pill Bottle (Salicylic Acid)"
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 1ff2b2f2c56..16bd6f4caa8 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -83,13 +83,14 @@
return
/obj/item/storage/AltClick(mob/user)
- if(Adjacent(user) && !user.incapacitated(FALSE, TRUE, TRUE))
+ if(ishuman(user) && Adjacent(user) && !user.incapacitated(FALSE, TRUE, TRUE))
orient2hud(user)
if(user.s_active)
user.s_active.close(user)
show_to(user)
playsound(loc, "rustle", 50, 1, -5)
add_fingerprint(user)
+ return ..()
/obj/item/storage/proc/return_inv()
@@ -481,10 +482,10 @@
return ..()
/obj/item/storage/emp_act(severity)
- if(!istype(loc, /mob/living))
- for(var/obj/O in contents)
- O.emp_act(severity)
..()
+ for(var/i in contents)
+ var/atom/A = i
+ A.emp_act(severity)
/obj/item/storage/hear_talk(mob/living/M as mob, list/message_pieces)
..()
@@ -540,7 +541,7 @@
return depth
/obj/item/storage/serialize()
- var data = ..()
+ var/data = ..()
var/list/content_list = list()
data["content"] = content_list
data["slots"] = storage_slots
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index f965907c5ba..6cf011bc2c3 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -121,19 +121,6 @@
desc = "A sleek, sturdy box"
icon_state = "box_of_doom"
-/obj/item/storage/box/syndie_kit/romerol
- name = "Romerol Kit"
- desc = "A box containing a deadly virus capable of reanimating dead as zombies."
- max_w_class = WEIGHT_CLASS_NORMAL
- can_hold = list(/obj/item/reagent_containers/glass/bottle/romerol,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/dropper)
-
-/obj/item/storage/box/syndie_kit/romerol/New()
- ..()
- new /obj/item/reagent_containers/glass/bottle/romerol(src)
- new /obj/item/reagent_containers/syringe(src)
- new /obj/item/reagent_containers/dropper(src)
- return
-
/obj/item/storage/box/syndie_kit/space
name = "Boxed Space Suit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/syndicate/black/red, /obj/item/clothing/head/helmet/space/syndicate/black/red, /obj/item/tank/emergency_oxygen/syndi, /obj/item/clothing/mask/gas/syndicate)
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 6782057d928..a39050cba47 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -189,8 +189,8 @@
L.apply_effect(STUTTER, stunforce)
if(user)
- user.lastattacked = L
- L.lastattacker = user
+ L.lastattacker = user.real_name
+ L.lastattackerckey = user.ckey
L.visible_message("[user] has stunned [L] with [src]!", \
"[user] has stunned you with [src]!")
add_attack_logs(user, L, "stunned")
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index 11355b34170..a82d6c0c223 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -53,13 +53,8 @@ obj/item/tank/oxygen/empty/New()
/obj/item/tank/anesthetic/New()
..()
-
- air_contents.oxygen = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
-
- var/datum/gas/sleeping_agent/trace_gas = new()
- trace_gas.moles = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
-
- air_contents.trace_gases += trace_gas
+ air_contents.oxygen = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD
+ air_contents.sleeping_agent = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD
/*
* Air
diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm
index 2375c42db65..55dc189fc9b 100644
--- a/code/game/objects/items/weapons/tanks/watertank.dm
+++ b/code/game/objects/items/weapons/tanks/watertank.dm
@@ -119,7 +119,7 @@
amount_per_transfer_from_this = 50
possible_transfer_amounts = list(25,50,100)
volume = 500
- flags = NODROP | NOBLUDGEON
+ flags = NOBLUDGEON
container_type = OPENCONTAINER
var/obj/item/watertank/tank
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index 4ac9651ea65..33aeddeaab0 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -115,7 +115,7 @@ Frequency:
to_chat(user, "\The [src] is malfunctioning.")
return
var/list/L = list( )
- for(var/obj/machinery/computer/teleporter/com in world)
+ for(var/obj/machinery/computer/teleporter/com in GLOB.machines)
if(com.target)
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
L["[com.id] (Active)"] = com.target
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
deleted file mode 100644
index 012fcf79b10..00000000000
--- a/code/game/objects/items/weapons/tools.dm
+++ /dev/null
@@ -1,785 +0,0 @@
-#define HEALPERWELD 15
-
-/* Tools!
- * Note: Multitools are in devices
- *
- * Contains:
- * Wrench
- * Screwdriver
- * Wirecutters
- * Welding Tool
- * Crowbar
- * Revolver Conversion Kit
- */
-
-//Wrench
-/obj/item/wrench
- name = "wrench"
- desc = "A wrench with common uses. Can be found in your hand."
- icon = 'icons/obj/tools.dmi'
- icon_state = "wrench"
- flags = CONDUCT
- slot_flags = SLOT_BELT
- force = 5
- throwforce = 7
- usesound = 'sound/items/ratchet.ogg'
- w_class = WEIGHT_CLASS_SMALL
- materials = list(MAT_METAL=150)
- origin_tech = "materials=1;engineering=1"
- attack_verb = list("bashed", "battered", "bludgeoned", "whacked")
- toolspeed = 1
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
-
-/obj/item/wrench/suicide_act(mob/user)
- user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
- return BRUTELOSS
-
-/obj/item/wrench/cyborg
- name = "automatic wrench"
- desc = "An advanced robotic wrench. Can be found in construction cyborgs."
- toolspeed = 0.5
-
-/obj/item/wrench/brass
- name = "brass wrench"
- desc = "A brass wrench. It's faintly warm to the touch."
- icon_state = "wrench_brass"
- toolspeed = 0.5
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/wrench/abductor
- name = "alien wrench"
- desc = "A polarized wrench. It causes anything placed between the jaws to turn."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "wrench"
- usesound = 'sound/effects/empulse.ogg'
- toolspeed = 0.1
- origin_tech = "materials=5;engineering=5;abductor=3"
-
-/obj/item/wrench/power
- name = "hand drill"
- desc = "A simple powered drill with a bolt bit."
- icon_state = "drill_bolt"
- item_state = "drill"
- usesound = 'sound/items/drill_use.ogg'
- materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25)
- origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get
- force = 8 //might or might not be too high, subject to change
- throwforce = 8
- attack_verb = list("drilled", "screwed", "jabbed")
- toolspeed = 0.25
-
-/obj/item/wrench/power/attack_self(mob/user)
- playsound(get_turf(user),'sound/items/change_drill.ogg', 50, 1)
- var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power
- to_chat(user, "You attach the screwdriver bit to [src].")
- qdel(src)
- user.put_in_active_hand(s_drill)
-
-/obj/item/wrench/power/suicide_act(mob/user)
- user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/wrench/medical
- name = "medical wrench"
- desc = "A medical wrench with common (medical?) uses. Can be found in your hand."
- icon_state = "wrench_medical"
- force = 2 //MEDICAL
- throwforce = 4
- origin_tech = "materials=1;engineering=1;biotech=3"
- attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked")
-
-/obj/item/wrench/medical/suicide_act(mob/user)
- user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!")
- // TODO Make them glow with the power of the M E D I C A L W R E N C H
- // during their ascension
-
- // Stun stops them from wandering off
- user.Stun(5)
- playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1)
-
- // Let the sound effect finish playing
- sleep(20)
-
- if(!user)
- return
-
- for(var/obj/item/W in user)
- user.unEquip(W)
-
- var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc)
- W.add_fingerprint(user)
- W.desc += " For some reason, it reminds you of [user.name]."
-
- if(!user)
- return
-
- user.dust()
- return OBLITERATION
-
-//Screwdriver
-/obj/item/screwdriver
- name = "screwdriver"
- desc = "You can be totally screwy with this."
- icon = 'icons/obj/tools.dmi'
- icon_state = "screwdriver_map"
- flags = CONDUCT
- slot_flags = SLOT_BELT
- force = 5
- w_class = WEIGHT_CLASS_TINY
- throwforce = 5
- throw_speed = 3
- throw_range = 5
- materials = list(MAT_METAL=75)
- attack_verb = list("stabbed")
- hitsound = 'sound/weapons/bladeslice.ogg'
- usesound = 'sound/items/screwdriver.ogg'
- toolspeed = 1
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
- var/random_color = TRUE //if the screwdriver uses random coloring
-
-/obj/item/screwdriver/nuke
- name = "screwdriver"
- desc = "A screwdriver with an ultra thin tip."
- icon_state = "screwdriver_nuke"
- toolspeed = 0.5
-
-/obj/item/screwdriver/suicide_act(mob/user)
- user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/screwdriver/New(loc, var/param_color = null)
- ..()
- if(random_color)
- if(!param_color)
- param_color = pick("red","blue","pink","brown","green","cyan","yellow")
- icon_state = "screwdriver_[param_color]"
-
- if (prob(75))
- src.pixel_y = rand(0, 16)
-
-/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user)
- if(!istype(M) || user.a_intent == INTENT_HELP)
- return ..()
- if(user.zone_selected != "eyes" && user.zone_selected != "head")
- return ..()
- if(HAS_TRAIT(user, TRAIT_PACIFISM))
- to_chat(user, "You don't want to harm [M]!")
- return
- if((CLUMSY in user.mutations) && prob(50))
- M = user
- return eyestab(M,user)
-
-/obj/item/screwdriver/brass
- name = "brass screwdriver"
- desc = "A screwdriver made of brass. The handle feels freezing cold."
- icon_state = "screwdriver_brass"
- toolspeed = 0.5
- random_color = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/screwdriver/abductor
- name = "alien screwdriver"
- desc = "An ultrasonic screwdriver."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "screwdriver"
- usesound = 'sound/items/pshoom.ogg'
- toolspeed = 0.1
- random_color = FALSE
-
-/obj/item/screwdriver/power
- name = "hand drill"
- desc = "A simple hand drill with a screwdriver bit attached."
- icon_state = "drill_screw"
- item_state = "drill"
- materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25)
- origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get
- force = 8 //might or might not be too high, subject to change
- throwforce = 8
- throw_speed = 2
- throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far
- attack_verb = list("drilled", "screwed", "jabbed","whacked")
- hitsound = 'sound/items/drill_hit.ogg'
- usesound = 'sound/items/drill_use.ogg'
- toolspeed = 0.25
- random_color = FALSE
-
-/obj/item/screwdriver/power/suicide_act(mob/user)
- user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/screwdriver/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, 1)
- var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power
- to_chat(user, "You attach the bolt driver bit to [src].")
- qdel(src)
- user.put_in_active_hand(b_drill)
-
-/obj/item/screwdriver/cyborg
- name = "powered screwdriver"
- desc = "An electrical screwdriver, designed to be both precise and quick."
- usesound = 'sound/items/drill_use.ogg'
- toolspeed = 0.5
-
-//Wirecutters
-/obj/item/wirecutters
- name = "wirecutters"
- desc = "This cuts wires."
- icon = 'icons/obj/tools.dmi'
- icon_state = "cutters"
- flags = CONDUCT
- slot_flags = SLOT_BELT
- force = 6
- throw_speed = 3
- throw_range = 7
- w_class = WEIGHT_CLASS_SMALL
- materials = list(MAT_METAL=80)
- origin_tech = "materials=1;engineering=1"
- attack_verb = list("pinched", "nipped")
- hitsound = 'sound/items/wirecutter.ogg'
- usesound = 'sound/items/wirecutter.ogg'
- sharp = 1
- toolspeed = 1
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
- var/random_color = TRUE
-
-/obj/item/wirecutters/New(loc, param_color = null)
- ..()
- if(random_color)
- if(!param_color)
- param_color = pick("yellow", "red")
- icon_state = "cutters_[param_color]"
-
-/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user)
- if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable))
- user.visible_message("[user] cuts [C]'s restraints with [src]!")
- QDEL_NULL(C.handcuffed)
- if(C.buckled && C.buckled.buckle_requires_restraints)
- C.buckled.unbuckle_mob(C)
- C.update_handcuffed()
- return
- else
- ..()
-
-/obj/item/wirecutters/suicide_act(mob/user)
- user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- playsound(loc, usesound, 50, 1, -1)
- return BRUTELOSS
-
-/obj/item/wirecutters/brass
- name = "brass wirecutters"
- desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch."
- icon_state = "cutters_brass"
- toolspeed = 0.5
- random_color = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/wirecutters/abductor
- name = "alien wirecutters"
- desc = "Extremely sharp wirecutters, made out of a silvery-green metal."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "cutters"
- toolspeed = 0.1
- origin_tech = "materials=5;engineering=4;abductor=3"
- random_color = FALSE
-
-/obj/item/wirecutters/cyborg
- name = "wirecutters"
- desc = "This cuts wires."
- toolspeed = 0.5
-
-/obj/item/wirecutters/power
- name = "jaws of life"
- desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a cutting head."
- icon_state = "jaws_cutter"
- item_state = "jawsoflife"
- origin_tech = "materials=2;engineering=2"
- materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25)
- usesound = 'sound/items/jaws_cut.ogg'
- toolspeed = 0.25
- random_color = FALSE
-
-/obj/item/wirecutters/power/suicide_act(mob/user)
- user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!")
- playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- var/obj/item/organ/external/head/head = H.bodyparts_by_name["head"]
- if(head)
- head.droplimb(0, DROPLIMB_BLUNT, FALSE, TRUE)
- playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1)
- return BRUTELOSS
-
-/obj/item/wirecutters/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
- var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power
- to_chat(user, "You attach the pry jaws to [src].")
- qdel(src)
- user.put_in_active_hand(pryjaws)
-
-//Welding Tool
-/obj/item/weldingtool
- name = "welding tool"
- desc = "A standard edition welder provided by Nanotrasen."
- icon = 'icons/obj/tools.dmi'
- icon_state = "welder"
- item_state = "welder"
- flags = CONDUCT
- slot_flags = SLOT_BELT
- force = 3
- throwforce = 5
- throw_speed = 3
- throw_range = 5
- hitsound = "swing_hit"
- usesound = 'sound/items/welder.ogg'
- var/acti_sound = 'sound/items/welderactivate.ogg'
- var/deac_sound = 'sound/items/welderdeactivate.ogg'
- w_class = WEIGHT_CLASS_SMALL
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
- resistance_flags = FIRE_PROOF
- materials = list(MAT_METAL=70, MAT_GLASS=30)
- origin_tech = "engineering=1;plasmatech=1"
- toolspeed = 1
- var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
- var/status = 1 //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower)
- var/max_fuel = 20 //The max amount of fuel the welder can hold
- var/change_icons = 1
- var/can_off_process = 0
- var/light_intensity = 2 //how powerful the emitted light is when used.
- var/nextrefueltick = 0
-
-/obj/item/weldingtool/New()
- ..()
- create_reagents(max_fuel)
- reagents.add_reagent("fuel", max_fuel)
- update_icon()
-
-/obj/item/weldingtool/examine(mob/user)
- . = ..()
- if(get_dist(user, src) <= 0)
- . += "It contains [get_fuel()] unit\s of fuel out of [max_fuel]."
-
-/obj/item/weldingtool/suicide_act(mob/user)
- user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!")
- return FIRELOSS
-
-/obj/item/weldingtool/proc/update_torch()
- overlays.Cut()
- if(welding)
- overlays += "[initial(icon_state)]-on"
- item_state = "[initial(item_state)]1"
- else
- item_state = "[initial(item_state)]"
-
-/obj/item/weldingtool/update_icon()
- if(change_icons)
- var/ratio = get_fuel() / max_fuel
- ratio = Ceiling(ratio*4) * 25
- if(ratio == 100)
- icon_state = initial(icon_state)
- else
- icon_state = "[initial(icon_state)][ratio]"
- update_torch()
- ..()
-
-/obj/item/weldingtool/process()
- switch(welding)
- if(0)
- force = 3
- damtype = "brute"
- update_icon()
- if(!can_off_process)
- STOP_PROCESSING(SSobj, src)
- return
- //Welders left on now use up fuel, but lets not have them run out quite that fast
- if(1)
- force = 15
- damtype = "fire"
- if(prob(5))
- remove_fuel(1)
- update_icon()
-
- //This is to start fires. process() is only called if the welder is on.
- var/turf/location = loc
- if(ismob(location))
- var/mob/M = location
- if(M.l_hand == src || M.r_hand == src)
- location = get_turf(M)
- if(isturf(location))
- location.hotspot_expose(700, 5)
-
-/obj/item/weldingtool/attackby(obj/item/I, mob/user, params)
- if(isscrewdriver(I))
- flamethrower_screwdriver(I, user)
- else if(istype(I, /obj/item/stack/rods))
- flamethrower_rods(I, user)
- else
- ..()
-
-/obj/item/weldingtool/attack(mob/M, mob/user)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/S = H.bodyparts_by_name[user.zone_selected]
-
- if(!S)
- return
-
- if(!S.is_robotic() || user.a_intent != INTENT_HELP || S.open == 2)
- return ..()
-
- if(!isOn()) //why wasn't this being checked already?
- to_chat(user, "Turn on [src] before attempting repairs!")
- return 1
-
- if(S.brute_dam > ROBOLIMB_SELF_REPAIR_CAP)
- to_chat(user, "The damage is far too severe to patch over externally.")
- return
-
- if(!S.brute_dam)
- to_chat(user, "Nothing to fix!")
- return
-
- if(get_fuel() >= 1)
- if(H == user)
- if(!do_mob(user, H, 10))
- return 1
- if(!remove_fuel(1,null))
- to_chat(user, "Need more welding fuel!")
- var/rembrute = HEALPERWELD
- var/nrembrute = 0
- var/childlist
- if(!isnull(S.children))
- childlist = S.children.Copy()
- var/parenthealed = FALSE
- while(rembrute > 0)
- var/obj/item/organ/external/E
- if(S.brute_dam)
- E = S
- else if(LAZYLEN(childlist))
- E = pick_n_take(childlist)
- if(!E.brute_dam || !E.is_robotic())
- continue
- else if(S.parent && !parenthealed)
- E = S.parent
- parenthealed = TRUE
- if(!E.brute_dam || !E.is_robotic())
- break
- else
- break
- playsound(src.loc, usesound, 50, 1)
- nrembrute = max(rembrute - E.brute_dam, 0)
- E.heal_damage(rembrute,0,0,1)
- rembrute = nrembrute
- user.visible_message("\The [user] patches some dents on \the [M]'s [E.name] with \the [src].")
- if(H.bleed_rate && H.isSynthetic())
- H.bleed_rate = 0
- user.visible_message("\The [user] patches some leaks on [M] with \the [src].")
- return 1
- else
- return ..()
-
-/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity)
- if(!proximity)
- return
- if(welding)
- remove_fuel(1)
- var/turf/location = get_turf(user)
- location.hotspot_expose(700, 50, 1)
- if(get_fuel() <= 0)
- set_light(0)
-
- if(isliving(O))
- var/mob/living/L = O
- if(L.IgniteMob())
- message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire")
- log_game("[key_name(user)] set [key_name(L)] on fire")
-
-/obj/item/weldingtool/attack_self(mob/user)
- switched_on(user)
- if(welding)
- set_light(light_intensity)
-
- update_icon()
-
-//Returns the amount of fuel in the welder
-/obj/item/weldingtool/proc/get_fuel()
- return reagents.get_reagent_amount("fuel")
-
-//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use()
-/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null)
- if(!welding || !check_fuel())
- return FALSE
- if(get_fuel() >= amount)
- reagents.remove_reagent("fuel", amount)
- check_fuel()
- if(M)
- M.flash_eyes(light_intensity)
- return TRUE
- else
- if(M)
- to_chat(M, "You need more welding fuel to complete this task.")
- return FALSE
-
-//Returns whether or not the welding tool is currently on.
-/obj/item/weldingtool/proc/isOn()
- return welding
-
-//Turns off the welder if there is no more fuel (does this really need to be its own proc?)
-/obj/item/weldingtool/proc/check_fuel(mob/user)
- if(get_fuel() <= 0 && welding)
- switched_on(user)
- update_icon()
- //mob icon update
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_r_hand(0)
- M.update_inv_l_hand(0)
- return 0
- return 1
-
-//Switches the welder on
-/obj/item/weldingtool/proc/switched_on(mob/user)
- if(!status)
- to_chat(user, "[src] can't be turned on while unsecured!")
- return
- welding = !welding
- if(welding)
- if(get_fuel() >= 1)
- to_chat(user, "You switch [src] on.")
- playsound(loc, acti_sound, 50, 1)
- force = 15
- damtype = "fire"
- hitsound = 'sound/items/welder.ogg'
- update_icon()
- START_PROCESSING(SSobj, src)
- else
- to_chat(user, "You need more fuel!")
- switched_off(user)
- else
- if(user)
- to_chat(user, "You switch [src] off.")
- playsound(loc, deac_sound, 50, 1)
- switched_off(user)
-
-//Switches the welder off
-/obj/item/weldingtool/proc/switched_off(mob/user)
- welding = 0
- set_light(0)
-
- force = 3
- damtype = "brute"
- hitsound = "swing_hit"
- update_icon()
-
-/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user)
- if(welding)
- to_chat(user, "Turn it off first!")
- return
- status = !status
- if(status)
- to_chat(user, "You resecure [src].")
- else
- to_chat(user, "[src] can now be attached and modified.")
- add_fingerprint(user)
-
-/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user)
- if(!status)
- var/obj/item/stack/rods/R = I
- if(R.use(1))
- var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc)
- if(!remove_item_from_storage(F))
- user.unEquip(src)
- loc = F
- F.weldtool = src
- add_fingerprint(user)
- to_chat(user, "You add a rod to a welder, starting to build a flamethrower.")
- user.put_in_hands(F)
- else
- to_chat(user, "You need one rod to start building a flamethrower!")
-
-/obj/item/weldingtool/largetank
- name = "Industrial Welding Tool"
- desc = "A slightly larger welder with a larger tank."
- icon_state = "indwelder"
- max_fuel = 40
- materials = list(MAT_METAL=70, MAT_GLASS=60)
- origin_tech = "engineering=2;plasmatech=2"
-
-/obj/item/weldingtool/largetank/cyborg
- name = "integrated welding tool"
- desc = "An advanced welder designed to be used in robotic systems."
- toolspeed = 0.5
-
-/obj/item/weldingtool/largetank/flamethrower_screwdriver()
- return
-
-/obj/item/weldingtool/mini
- name = "emergency welding tool"
- desc = "A miniature welder used during emergencies."
- icon_state = "miniwelder"
- max_fuel = 10
- w_class = WEIGHT_CLASS_TINY
- materials = list(MAT_METAL=30, MAT_GLASS=10)
- change_icons = 0
-
-/obj/item/weldingtool/mini/flamethrower_screwdriver()
- return
-
-/obj/item/weldingtool/abductor
- name = "alien welding tool"
- desc = "An alien welding tool. Whatever fuel it uses, it never runs out."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "welder"
- toolspeed = 0.1
- light_intensity = 0
- change_icons = 0
- origin_tech = "plasmatech=5;engineering=5;abductor=3"
- can_off_process = 1
-
-/obj/item/weldingtool/abductor/process()
- if(get_fuel() <= max_fuel)
- reagents.add_reagent("fuel", 1)
- ..()
-
-/obj/item/weldingtool/hugetank
- name = "Upgraded Welding Tool"
- desc = "An upgraded welder based off the industrial welder."
- icon_state = "upindwelder"
- item_state = "upindwelder"
- max_fuel = 80
- materials = list(MAT_METAL=70, MAT_GLASS=120)
- origin_tech = "engineering=3;plasmatech=2"
-
-/obj/item/weldingtool/experimental
- name = "Experimental Welding Tool"
- desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes."
- icon_state = "exwelder"
- item_state = "exwelder"
- max_fuel = 40
- materials = list(MAT_METAL=70, MAT_GLASS=120)
- origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4"
- change_icons = 0
- can_off_process = 1
- light_intensity = 1
- toolspeed = 0.5
- var/last_gen = 0
-
-/obj/item/weldingtool/experimental/brass
- name = "brass welding tool"
- desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
- icon_state = "brasswelder"
- item_state = "brasswelder"
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-obj/item/weldingtool/experimental/process()
- ..()
- if(get_fuel() < max_fuel && nextrefueltick < world.time)
- nextrefueltick = world.time + 10
- reagents.add_reagent("fuel", 1)
-
-//Crowbar
-/obj/item/crowbar
- name = "pocket crowbar"
- desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors."
- icon = 'icons/obj/tools.dmi'
- icon_state = "crowbar"
- item_state = "crowbar"
- usesound = 'sound/items/crowbar.ogg'
- flags = CONDUCT
- slot_flags = SLOT_BELT
- force = 5
- throwforce = 7
- item_state = "crowbar"
- w_class = WEIGHT_CLASS_SMALL
- materials = list(MAT_METAL=50)
- origin_tech = "engineering=1;combat=1"
- attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked")
- toolspeed = 1
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
-
-/obj/item/crowbar/red
- icon_state = "crowbar_red"
- item_state = "crowbar_red"
- force = 8
-
-/obj/item/crowbar/brass
- name = "brass crowbar"
- desc = "A brass crowbar. It feels faintly warm to the touch."
- icon_state = "crowbar_brass"
- item_state = "crowbar_brass"
- toolspeed = 0.5
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/crowbar/abductor
- name = "alien crowbar"
- desc = "A hard-light crowbar. It appears to pry by itself, without any effort required."
- icon = 'icons/obj/abductor.dmi'
- usesound = 'sound/weapons/sonic_jackhammer.ogg'
- icon_state = "crowbar"
- toolspeed = 0.1
- origin_tech = "combat=4;engineering=4;abductor=3"
-
-/obj/item/crowbar/large
- name = "crowbar"
- desc = "It's a big crowbar. It doesn't fit in your pockets, because its too big."
- force = 12
- w_class = WEIGHT_CLASS_NORMAL
- throw_speed = 3
- throw_range = 3
- materials = list(MAT_METAL=70)
- icon_state = "crowbar_large"
- item_state = "crowbar_large"
- toolspeed = 0.5
-
-/obj/item/crowbar/cyborg
- name = "hydraulic crowbar"
- desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs."
- usesound = 'sound/items/jaws_pry.ogg'
- force = 10
- toolspeed = 0.5
-
-/obj/item/crowbar/power
- name = "jaws of life"
- desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a prying head."
- icon_state = "jaws_pry"
- item_state = "jawsoflife"
- materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25)
- origin_tech = "materials=2;engineering=2"
- usesound = 'sound/items/jaws_pry.ogg'
- force = 15
- toolspeed = 0.25
- var/airlock_open_time = 100 // Time required to open powered airlocks
-
-/obj/item/crowbar/power/suicide_act(mob/user)
- user.visible_message("[user] is putting [user.p_their()] head in [src]. It looks like [user.p_theyre()] trying to commit suicide!")
- playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1)
- return BRUTELOSS
-
-/obj/item/crowbar/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
- var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power
- to_chat(user, "You attach the cutting jaws to [src].")
- qdel(src)
- user.put_in_active_hand(cutjaws)
-
-// Conversion kit
-/obj/item/conversion_kit
- name = "\improper Revolver Conversion Kit"
- desc = "A professional conversion kit used to convert any knock off revolver into the real deal capable of shooting lethal .357 rounds without the possibility of catastrophic failure."
- icon_state = "kit"
- flags = CONDUCT
- w_class = WEIGHT_CLASS_SMALL
- origin_tech = "combat=2"
- var/open = 0
-
-/obj/item/conversion_kit/New()
- ..()
- update_icon()
-
-/obj/item/conversion_kit/update_icon()
- icon_state = "[initial(icon_state)]_[open]"
-
-/obj/item/conversion_kit/attack_self(mob/user)
- open = !open
- to_chat(user, "You [open ? "open" : "close"] the conversion kit.")
- update_icon()
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 57c9a5301f6..ed857c18ded 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -179,6 +179,7 @@
slot_flags = SLOT_BACK
force_unwielded = 5
force_wielded = 24
+ toolspeed = 0.25
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
usesound = 'sound/items/crowbar.ogg'
@@ -542,6 +543,7 @@
w_class = WEIGHT_CLASS_BULKY // can't fit in backpacks
force_unwielded = 15 //still pretty robust
force_wielded = 40 //you'll gouge their eye out! Or a limb...maybe even their entire body!
+ hitsound = null // Handled in the snowflaked attack proc
wieldsound = 'sound/weapons/chainsawstart.ogg'
hitsound = null
armour_penetration = 35
diff --git a/code/game/objects/items/weapons/whetstone.dm b/code/game/objects/items/weapons/whetstone.dm
index f74f8d28f57..d2ab4b2733f 100644
--- a/code/game/objects/items/weapons/whetstone.dm
+++ b/code/game/objects/items/weapons/whetstone.dm
@@ -34,15 +34,15 @@
if(TH.force_wielded > initial(TH.force_wielded))
to_chat(user, "[TH] has already been refined before. It cannot be sharpened further!")
return
- TH.force_wielded = Clamp(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay
+ TH.force_wielded = clamp(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay
if(I.force > initial(I.force))
to_chat(user, "[I] has already been refined before. It cannot be sharpened further!")
return
user.visible_message("[user] sharpens [I] with [src]!", "You sharpen [I], making it much more deadly than before.")
if(!requires_sharpness)
I.sharp = 1
- I.force = Clamp(I.force + increment, 0, max)
- I.throwforce = Clamp(I.throwforce + increment, 0, max)
+ I.force = clamp(I.force + increment, 0, max)
+ I.throwforce = clamp(I.throwforce + increment, 0, max)
I.name = "[prefix] [I.name]"
playsound(get_turf(src), usesound, 50, 1)
name = "worn out [name]"
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index e1464e47e48..bbd43db7c1e 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -30,9 +30,9 @@
return 0
var/armor_protection = 0
if(damage_flag)
- armor_protection = armor[damage_flag]
+ armor_protection = armor.getRating(damage_flag)
if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor.
- armor_protection = Clamp(armor_protection - armour_penetration, min(armor_protection, 0), 100)
+ armor_protection = clamp(armor_protection - armour_penetration, min(armor_protection, 0), 100)
return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION)
///the sound played when the obj is damaged.
@@ -201,7 +201,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
return
..()
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
- take_damage(Clamp(0.02 * exposed_temperature, 0, 20), BURN, "fire", 0)
+ take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, "fire", 0)
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF))
resistance_flags |= ON_FIRE
SSfires.processing[src] = src
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 112925515a0..d40c628ed90 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -1,15 +1,14 @@
/obj
//var/datum/module/mod //not used
var/origin_tech = null //Used by R&D to determine what research bonuses it grants.
- var/crit_fail = 0
+ var/crit_fail = FALSE
animate_movement = 2
- var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
- var/sharp = 0 // whether this object cuts
- var/in_use = 0 // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
+ var/sharp = FALSE // whether this object cuts
+ var/in_use = FALSE // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
var/damtype = "brute"
var/force = 0
- var/list/armor
+ var/datum/armor/armor
var/obj_integrity //defaults to max_integrity
var/max_integrity = 500
var/integrity_failure = 0 //0 if we have no special broken behavior
@@ -22,9 +21,9 @@
var/can_be_hit = TRUE //can this be bludgeoned by items?
- var/Mtoollink = 0 // variable to decide if an object should show the multitool menu linking menu, not all objects use it
+ var/Mtoollink = FALSE // variable to decide if an object should show the multitool menu linking menu, not all objects use it
- var/being_shocked = 0
+ var/being_shocked = FALSE
var/speed_process = FALSE
var/on_blueprints = FALSE //Are we visible on the station blueprints at roundstart?
@@ -33,8 +32,6 @@
/obj/New()
..()
- if(!armor)
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
if(obj_integrity == null)
obj_integrity = max_integrity
if(on_blueprints && isturf(loc))
@@ -44,25 +41,34 @@
else
T.add_blueprints_preround(src)
-/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = GLOB.default_state)
+/obj/Initialize(mapload)
+ . = ..()
+ if(islist(armor))
+ armor = getArmor(arglist(armor))
+ else if(!armor)
+ armor = getArmor()
+ else if(!istype(armor, /datum/armor))
+ stack_trace("Invalid type [armor.type] found in .armor during /obj Initialize()")
+
+/obj/Topic(href, href_list, nowindow = FALSE, datum/topic_state/state = GLOB.default_state)
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
- return 1
+ return TRUE
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
// Instead any such checks are made in CanUseTopic()
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
CouldUseTopic(usr)
- return 0
+ return FALSE
CouldNotUseTopic(usr)
- return 1
+ return TRUE
-/obj/proc/CouldUseTopic(var/mob/user)
+/obj/proc/CouldUseTopic(mob/user)
var/atom/host = nano_host()
host.add_fingerprint(user)
-/obj/proc/CouldNotUseTopic(var/mob/user)
+/obj/proc/CouldNotUseTopic(mob/user)
// Nada
/obj/Destroy()
@@ -110,23 +116,23 @@
// null if object handles breathing logic for lifeform
// datum/air_group to tell lifeform to process using that breath return
//DEFAULT: Take air from turf to give to have mob process
- if(breath_request>0)
+ if(breath_request > 0)
return remove_air(breath_request)
else
return null
/obj/proc/updateUsrDialog()
if(in_use)
- var/is_in_use = 0
+ var/is_in_use = FALSE
var/list/nearby = viewers(1, src)
for(var/mob/M in nearby)
if((M.client && M.machine == src))
- is_in_use = 1
+ is_in_use = TRUE
src.attack_hand(M)
if(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot))
if(!(usr in nearby))
if(usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
- is_in_use = 1
+ is_in_use = TRUE
src.attack_ai(usr)
// check for TK users
@@ -134,8 +140,8 @@
if(istype(usr, /mob/living/carbon/human))
if(istype(usr.l_hand, /obj/item/tk_grab) || istype(usr.r_hand, /obj/item/tk_grab/))
if(!(usr in nearby))
- if(usr.client && usr.machine==src)
- is_in_use = 1
+ if(usr.client && usr.machine == src)
+ is_in_use = TRUE
src.attack_hand(usr)
in_use = is_in_use
@@ -143,15 +149,15 @@
// Check that people are actually using the machine. If not, don't update anymore.
if(in_use)
var/list/nearby = viewers(1, src)
- var/is_in_use = 0
+ var/is_in_use = FALSE
for(var/mob/M in nearby)
if((M.client && M.machine == src))
- is_in_use = 1
+ is_in_use = TRUE
src.interact(M)
var/ai_in_use = AutoUpdateAI(src)
if(!ai_in_use && !is_in_use)
- in_use = 0
+ in_use = FALSE
/obj/proc/interact(mob/user)
return
@@ -168,12 +174,12 @@
/atom/movable/proc/on_unset_machine(mob/user)
return
-/mob/proc/set_machine(var/obj/O)
+/mob/proc/set_machine(obj/O)
if(src.machine)
unset_machine()
src.machine = O
if(istype(O))
- O.in_use = 1
+ O.in_use = TRUE
/obj/item/proc/updateSelfDialog()
var/mob/M = src.loc
@@ -183,48 +189,48 @@
/obj/proc/hide(h)
return
-
/obj/proc/hear_talk(mob/M, list/message_pieces)
return
-/obj/proc/hear_message(mob/M as mob, text)
+/obj/proc/hear_message(mob/M, text)
-/obj/proc/multitool_menu(var/mob/user,var/obj/item/multitool/P)
+/obj/proc/multitool_menu(mob/user, obj/item/multitool/P)
return "NO MULTITOOL_MENU!"
-/obj/proc/linkWith(var/mob/user, var/obj/buffer, var/link/context)
- return 0
+/obj/proc/linkWith(mob/user, obj/buffer, context)
+ return FALSE
-/obj/proc/unlinkFrom(var/mob/user, var/obj/buffer)
- return 0
+/obj/proc/unlinkFrom(mob/user, obj/buffer)
+ return FALSE
-/obj/proc/canLink(var/obj/O, var/link/context)
- return 0
+/obj/proc/canLink(obj/O, list/context)
+ return FALSE
-/obj/proc/isLinkedWith(var/obj/O)
- return 0
+/obj/proc/isLinkedWith(obj/O)
+ return FALSE
-/obj/proc/getLink(var/idx)
+/obj/proc/getLink(idx)
return null
-/obj/proc/linkMenu(var/obj/O)
- var/dat=""
+/obj/proc/linkMenu(obj/O)
+ var/dat = ""
if(canLink(O, list()))
dat += " \[Link\] "
return dat
-/obj/proc/format_tag(var/label,var/varname, var/act="set_tag")
+/obj/proc/format_tag(label, varname, act = "set_tag")
var/value = vars[varname]
- if(!value || value=="")
- value="-----"
+ if(!value || value == "")
+ value = "-----"
return "[label]:[value]"
-/obj/proc/update_multitool_menu(mob/user as mob)
+/obj/proc/update_multitool_menu(mob/user)
var/obj/item/multitool/P = get_multitool(user)
if(!istype(P))
- return 0
+ return FALSE
+
var/dat = {"
[name] Configuration
@@ -246,15 +252,13 @@ a {
[name]
"}
if(allowed(user))//no, assistants, you're not ruining all vents on the station with just a multitool
- dat += multitool_menu(user,P)
+ dat += multitool_menu(user, P)
if(Mtoollink)
if(P)
if(P.buffer)
var/id = null
- if(istype(P.buffer, /obj/machinery/telecomms))
- id=P.buffer:id
- else if("id_tag" in P.buffer.vars)
- id=P.buffer:id_tag
+ if("id_tag" in P.buffer.vars)
+ id = P.buffer:id_tag
dat += "
MULTITOOL BUFFER: [P.buffer] [id ? "([id])" : ""]"
dat += linkMenu(P.buffer)
@@ -311,12 +315,12 @@ a {
/obj/singularity_pull(S, current_size)
..()
if(!anchored || current_size >= STAGE_FIVE)
- step_towards(src,S)
+ step_towards(src, S)
-/obj/proc/container_resist(var/mob/living)
+/obj/proc/container_resist(mob/living)
return
-/obj/proc/CanAStarPass()
+/obj/proc/CanAStarPass(ID, dir, caller)
. = !density
/obj/proc/on_mob_move(dir, mob/user)
@@ -343,6 +347,7 @@ a {
.["Make speed process"] = "?_src_=vars;makespeedy=[UID()]"
else
.["Make normal process"] = "?_src_=vars;makenormalspeed=[UID()]"
+ .["Modify armor values"] = "?_src_=vars;modifyarmor=[UID()]"
/obj/proc/check_uplink_validity()
- return 1
+ return TRUE
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 663f210df3e..b1ed99357ad 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -7,8 +7,6 @@
var/broken = FALSE
/obj/structure/New()
- if (!armor)
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
..()
if(smooth)
if(SSticker && SSticker.current_state == GAME_STATE_PLAYING)
@@ -20,6 +18,11 @@
if(SSticker)
GLOB.cameranet.updateVisibility(src)
+/obj/structure/Initialize(mapload)
+ if(!armor)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
+ return ..()
+
/obj/structure/Destroy()
if(SSticker)
GLOB.cameranet.updateVisibility(src)
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index 1de93f4d583..033787cce75 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -141,7 +141,6 @@
return ..()
/obj/structure/alien/weeds/proc/Life()
- set background = BACKGROUND_ENABLED
var/turf/U = get_turf(src)
if(istype(U, /turf/space))
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 82487dbd0ae..04373502832 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -12,6 +12,8 @@
var/opened = FALSE
var/welded = FALSE
var/locked = FALSE
+ var/large = TRUE
+ var/can_be_emaged = FALSE
var/wall_mounted = 0 //never solid (You can always pass over it)
var/lastbang
var/sound = 'sound/machines/click.ogg'
@@ -143,84 +145,21 @@
/obj/structure/closet/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/rcs) && !opened)
- if(user in contents) //to prevent self-teleporting.
- return
var/obj/item/rcs/E = W
- if(E.rcell && (E.rcell.charge >= E.chargecost))
- if(!is_level_reachable(z))
- to_chat(user, "The rapid-crate-sender can't locate any telepads!")
- return
- if(E.mode == 0)
- if(!E.teleporting)
- var/list/L = list()
- var/list/areaindex = list()
- for(var/obj/machinery/telepad_cargo/R in world)
- if(R.stage == 0)
- var/turf/T = get_turf(R)
- var/tmpname = T.loc.name
- if(areaindex[tmpname])
- tmpname = "[tmpname] ([++areaindex[tmpname]])"
- else
- areaindex[tmpname] = 1
- L[tmpname] = R
- var/desc = input("Please select a telepad.", "RCS") in L
- E.pad = L[desc]
- if(!Adjacent(user))
- to_chat(user, "Unable to teleport, too far from crate.")
- return
- playsound(E.loc, E.usesound, 50, 1)
- to_chat(user, "Teleporting [name]...")
- E.teleporting = 1
- if(!do_after(user, 50 * E.toolspeed, target = src))
- E.teleporting = 0
- return
- E.teleporting = 0
- if(user in contents)
- to_chat(user, "Error: User located in container--aborting for safety.")
- playsound(E.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
- return
- if(!(E.rcell && E.rcell.use(E.chargecost)))
- to_chat(user, "Unable to teleport, insufficient charge.")
- return
- do_sparks(5, 1, src)
- do_teleport(src, E.pad, 0)
- to_chat(user, "Teleport successful. [round(E.rcell.charge/E.chargecost)] charge\s left.")
- return
- else
- E.rand_x = rand(50,200)
- E.rand_y = rand(50,200)
- var/L = locate(E.rand_x, E.rand_y, 6)
- if(!Adjacent(user))
- to_chat(user, "Unable to teleport, too far from crate.")
- return
- playsound(E.loc, E.usesound, 50, 1)
- to_chat(user, "Teleporting [name]...")
- E.teleporting = 1
- if(!do_after(user, 50, E.toolspeed, target = src))
- E.teleporting = 0
- return
- E.teleporting = 0
- if(user in contents)
- to_chat(user, "Error: User located in container--aborting for safety.")
- playsound(E.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
- return
- if(!(E.rcell && E.rcell.use(E.chargecost)))
- to_chat(user, "Unable to teleport, insufficient charge.")
- return
- do_sparks(5, 1, src)
- do_teleport(src, L)
- to_chat(user, "Teleport successful. [round(E.rcell.charge/E.chargecost)] charge\s left.")
- return
- else
- to_chat(user, "Out of charges.")
- return
+ E.try_send_container(user, src)
return
if(opened)
if(istype(W, /obj/item/grab))
- MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet
- if(istype(W,/obj/item/tk_grab))
+ var/obj/item/grab/G = W
+ if(large)
+ MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
+ else
+ to_chat(user, "[src] is too small to stuff [G.affecting] into!")
+ if(istype(W, /obj/item/tk_grab))
return FALSE
+ if(user.a_intent != INTENT_HELP) // Stops you from putting your baton in the closet on accident
+ return
if(isrobot(user))
return
if(!user.drop_item()) //couldn't drop the item
@@ -228,13 +167,20 @@
return
if(W)
W.forceMove(loc)
+ return TRUE // It's resolved. No afterattack needed. Stops you from emagging lockers when putting in an emag
+ else if(can_be_emaged && (istype(W, /obj/item/card/emag) || istype(W, /obj/item/melee/energy/blade) && !broken))
+ emag_act(user)
else if(istype(W, /obj/item/stack/packageWrap))
return
else if(user.a_intent != INTENT_HARM)
- attack_hand(user)
+ closed_item_click(user)
else
return ..()
+// What happens when the closet is attacked by a random item not on harm mode
+/obj/structure/closet/proc/closed_item_click(mob/user)
+ attack_hand(user)
+
/obj/structure/closet/welder_act(mob/user, obj/item/I)
. = TRUE
if(!opened && user.loc == src)
@@ -284,7 +230,7 @@
add_fingerprint(user)
/obj/structure/closet/attack_ai(mob/user)
- if(isrobot(user) && Adjacent(user)) //Robots can open/close it, but not the AI
+ if(isrobot(user) && Adjacent(user) && !istype(user.loc, /obj/machinery/atmospherics)) //Robots can open/close it, but not the AI
attack_hand(user)
/obj/structure/closet/relaymove(mob/user)
diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
index 448fd6feb34..0da39d2255d 100644
--- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
@@ -115,6 +115,8 @@
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/glasses/sunglasses/big(src)
new /obj/item/clothing/glasses/sunglasses/big(src)
+ new /obj/item/clothing/accessory/lawyers_badge(src)
+ new /obj/item/clothing/accessory/lawyers_badge(src)
//Paramedic
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
index bba8dc2a866..5ffbdd0cda7 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
@@ -36,7 +36,7 @@
depotarea.armory_locker_looted()
/obj/structure/closet/secure_closet/syndicate/depot/attack_animal(mob/M)
- if(isanimal(M) && "syndicate" in M.faction)
+ if(isanimal(M) && ("syndicate" in M.faction))
to_chat(M, "The [src] resists your attack!")
return
return ..()
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 7616aa90877..f0a7336389b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -16,7 +16,7 @@
new /obj/item/storage/backpack/satchel_eng(src)
new /obj/item/storage/backpack/duffel/engineering(src)
new /obj/item/clothing/head/beret/ce(src)
- new /obj/item/areaeditor/blueprints(src)
+ new /obj/item/areaeditor/blueprints/ce(src)
new /obj/item/storage/box/permits(src)
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
index 096133b6e0d..7eab5858772 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
@@ -54,36 +54,33 @@
new /obj/item/storage/backpack/satchel/withwallet( src )
new /obj/item/radio/headset( src )
-/obj/structure/closet/secure_closet/personal/attackby(obj/item/W as obj, mob/user as mob, params)
- if(src.opened)
- if(istype(W, /obj/item/grab))
- src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet
- user.drop_item()
- if(W) W.forceMove(loc)
- else if(istype(W, /obj/item/card/id))
- if(src.broken)
- to_chat(user, "It appears to be broken.")
- return
- var/obj/item/card/id/I = W
- if(!I || !I.registered_name) return
- if(src == user.loc)
- to_chat(user, "You can't reach the lock from inside.")
- else if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name)))
- //they can open all lockers, or nobody owns this, or they own this locker
- src.locked = !( src.locked )
- if(src.locked)
- src.icon_state = src.icon_locked
- else
- src.icon_state = src.icon_closed
- registered_name = null
- desc = initial(desc)
-
- if(!src.registered_name && src.locked)
- src.registered_name = I.registered_name
- src.desc = "Owned by [I.registered_name]."
- else
- to_chat(user, "Access Denied")
- else if((istype(W, /obj/item/card/emag) || istype(W, /obj/item/melee/energy/blade)) && !broken)
- emag_act(user)
- else
+/obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params)
+ if(opened || !istype(W, /obj/item/card/id))
return ..()
+
+ if(broken)
+ to_chat(user, "It appears to be broken.")
+ return
+
+ var/obj/item/card/id/I = W
+ if(!I || !I.registered_name)
+ return
+
+ if(src == user.loc)
+ to_chat(user, "You can't reach the lock from inside.")
+
+ else if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name)))
+ //they can open all lockers, or nobody owns this, or they own this locker
+ locked = !locked
+ if(locked)
+ icon_state = icon_locked
+ else
+ icon_state = icon_closed
+ registered_name = null
+ desc = initial(desc)
+
+ if(!registered_name && locked)
+ registered_name = I.registered_name
+ desc = "Owned by [I.registered_name]."
+ else
+ to_chat(user, "Access Denied")
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index dbb3b8f283d..763717dc270 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -7,10 +7,10 @@
opened = 0
locked = 1
broken = 0
+ can_be_emaged = TRUE
max_integrity = 250
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
damage_deflection = 20
- var/large = 1
icon_closed = "secure"
var/icon_locked = "secure1"
icon_opened = "secureopen"
@@ -66,31 +66,8 @@
else
to_chat(user, "Access Denied")
-/obj/structure/closet/secure_closet/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/rcs))
- return ..()
-
- if(opened)
- if(istype(W, /obj/item/grab))
- if(large)
- MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet
- else
- to_chat(user, "The locker is too small to stuff [W:affecting] into!")
- if(isrobot(user))
- return
- if(!user.drop_item()) //couldn't drop the item
- to_chat(user, "\The [W] is stuck to your hand, you cannot put it in \the [src]!")
- return
- if(W)
- W.forceMove(loc)
- else if((istype(W, /obj/item/card/emag)||istype(W, /obj/item/melee/energy/blade)) && !broken)
- emag_act(user)
- else if(istype(W,/obj/item/stack/packageWrap) || istype(W,/obj/item/weldingtool))
- return ..(W, user)
- else if(user.a_intent != INTENT_HARM)
- togglelock(user)
- else
- return ..()
+/obj/structure/closet/secure_closet/closed_item_click(mob/user)
+ togglelock(user)
/obj/structure/closet/secure_closet/emag_act(mob/user)
if(!broken)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 6d4b47df6ab..be004a82912 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -426,7 +426,7 @@
icon_off = "wall-lockeroff"
//too small to put a man in
- large = 0
+ large = FALSE
/obj/structure/closet/secure_closet/wall/update_icon()
if(broken)
@@ -466,3 +466,4 @@
new /obj/item/gavelhammer(src)
new /obj/item/clothing/head/justice_wig(src)
new /obj/item/clothing/accessory/medal/legal(src)
+ new /obj/item/clothing/accessory/lawyers_badge(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm
index 501abd4922d..e285c6a0ae9 100644
--- a/code/game/objects/structures/crates_lockers/closets/statue.dm
+++ b/code/game/objects/structures/crates_lockers/closets/statue.dm
@@ -19,7 +19,7 @@
L.buckled = 0
L.anchored = 0
L.forceMove(src)
- L.disabilities += MUTE
+ L.mutations |= MUTE
max_integrity = L.health + 100 //stoning damaged mobs will result in easier to shatter statues
intialTox = L.getToxLoss()
intialFire = L.getFireLoss()
@@ -69,7 +69,7 @@
for(var/mob/living/M in src)
M.forceMove(loc)
- M.disabilities -= MUTE
+ M.mutations -= MUTE
M.take_overall_damage((M.health - obj_integrity - 100),0) //any new damage the statue incurred is transfered to the mob
..()
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index f9010c19415..2441a2d57d6 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -79,111 +79,42 @@
return TRUE
/obj/structure/closet/crate/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/rcs) && !src.opened)
- var/obj/item/rcs/E = W
- if(E.rcell && (E.rcell.charge >= E.chargecost))
- if(!is_level_reachable(src.z)) // This is inconsistent with the closet sending code
- to_chat(user, "The rapid-crate-sender can't locate any telepads!")
- return
- if(E.mode == 0)
- if(!E.teleporting)
- var/list/L = list()
- var/list/areaindex = list()
- for(var/obj/machinery/telepad_cargo/R in world)
- if(R.stage == 0)
- var/turf/T = get_turf(R)
- var/tmpname = T.loc.name
- if(areaindex[tmpname])
- tmpname = "[tmpname] ([++areaindex[tmpname]])"
- else
- areaindex[tmpname] = 1
- L[tmpname] = R
- var/desc = input("Please select a telepad.", "RCS") in L
- E.pad = L[desc]
- if(!Adjacent(user))
- to_chat(user, "Unable to teleport, too far from crate.")
- return
- playsound(E.loc, E.usesound, 50, 1)
- to_chat(user, "Teleporting [src.name]...")
- E.teleporting = TRUE
- if(!do_after(user, 50 * E.toolspeed, target = src))
- E.teleporting = 0
- return
- E.teleporting = 0
- if(!(E.rcell && E.rcell.use(E.chargecost)))
- to_chat(user, "Unable to teleport, insufficient charge.")
- return
- do_sparks(5, 1, src)
- do_teleport(src, E.pad, 0)
- to_chat(user, "Teleport successful. [round(E.rcell.charge/E.chargecost)] charge\s left.")
- return
-
- else
- E.rand_x = rand(50,200)
- E.rand_y = rand(50,200)
- var/L = locate(E.rand_x, E.rand_y, 6)
- if(!Adjacent(user))
- to_chat(user, "Unable to teleport, too far from crate.")
- return
- playsound(E.loc, E.usesound, 50, 1)
- to_chat(user, "Teleporting [src.name]...")
- E.teleporting = TRUE
- if(!do_after(user, 50 * E.toolspeed, target = src))
- E.teleporting = FALSE
- return
- E.teleporting = 0
- if(!(E.rcell && E.rcell.use(E.chargecost)))
- to_chat(user, "Unable to teleport, insufficient charge.")
- return
- do_sparks(5, 1, src)
- do_teleport(src, L)
- to_chat(user, "Teleport successful. [round(E.rcell.charge/E.chargecost)] charge\s left.")
- return
- else
- to_chat(user, "Out of charges.")
- return
-
- if(opened)
- if(isrobot(user))
- return
- if(!user.drop_item()) //couldn't drop the item
- to_chat(user, "\The [W] is stuck to your hand, you cannot put it in \the [src]!")
- return
- if(W)
- W.forceMove(loc)
- else if(istype(W, /obj/item/stack/packageWrap))
+ if(!opened && try_rig(W, user))
return
- else if(istype(W, /obj/item/stack/cable_coil))
+ return ..()
+
+/obj/structure/closet/crate/proc/try_rig(obj/item/W, mob/user)
+ if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(rigged)
to_chat(user, "[src] is already rigged!")
- return
+ return TRUE
if(C.use(15))
to_chat(user, "You rig [src].")
rigged = TRUE
else
to_chat(user, "You need atleast 15 wires to rig [src]!")
- return
- else if(istype(W, /obj/item/radio/electropack))
+ return TRUE
+ if(istype(W, /obj/item/radio/electropack))
if(rigged)
+ if(!user.drop_item())
+ to_chat(user, "[W] seems to be stuck to your hand!")
+ return TRUE
to_chat(user, "You attach [W] to [src].")
- user.drop_item()
W.forceMove(src)
- return
- else if(istype(W, /obj/item/wirecutters))
- if(rigged)
- to_chat(user, "You cut away the wiring.")
- playsound(loc, W.usesound, 100, 1)
- rigged = FALSE
- return
- else if(user.a_intent != INTENT_HARM)
- attack_hand(user)
- else
- return ..()
+ return TRUE
-/obj/structure/closet/singularity_act()
- dump_contents()
- ..()
+/obj/structure/closet/crate/wirecutter_act(mob/living/user, obj/item/I)
+ if(opened)
+ return
+ if(!rigged)
+ return
+
+ if(I.use_tool(src, user))
+ to_chat(user, "You cut away the wiring.")
+ playsound(loc, I.usesound, 100, 1)
+ rigged = FALSE
+ return TRUE
/obj/structure/closet/crate/welder_act()
return
@@ -229,9 +160,10 @@
max_integrity = 500
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
damage_deflection = 25
- var/tamperproof = 0
- broken = 0
- locked = 1
+ var/tamperproof = FALSE
+ broken = FALSE
+ locked = TRUE
+ can_be_emaged = TRUE
/obj/structure/closet/crate/secure/update_icon()
..()
@@ -306,17 +238,8 @@
else
src.toggle(user)
-
-/obj/structure/closet/crate/secure/attackby(obj/item/W, mob/user, params)
- if(is_type_in_list(W, list(/obj/item/stack/packageWrap, /obj/item/stack/cable_coil, /obj/item/radio/electropack, /obj/item/wirecutters,/obj/item/rcs)))
- return ..()
- if((istype(W, /obj/item/card/emag) || istype(W, /obj/item/melee/energy/blade)))
- emag_act(user)
- return
- if(!opened)
- src.togglelock(user)
- return
- return ..()
+/obj/structure/closet/crate/secure/closed_item_click(mob/user)
+ togglelock(user)
/obj/structure/closet/crate/secure/emag_act(mob/user)
if(locked)
diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm
index e2ab534923d..029b0a761ad 100644
--- a/code/game/objects/structures/curtains.dm
+++ b/code/game/objects/structures/curtains.dm
@@ -46,7 +46,7 @@
/obj/structure/curtain/screwdriver_act(mob/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(anchored)
user.visible_message("[user] unscrews [src] from the floor.", "You start to unscrew [src] from the floor...", "You hear rustling noises.")
@@ -65,7 +65,7 @@
if(anchored)
return
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
WIRECUTTER_ATTEMPT_DISMANTLE_MESSAGE
if(I.use_tool(src, user, 50, volume = I.tool_volume))
diff --git a/code/game/objects/structures/decor/machinery/telecomms.dm b/code/game/objects/structures/decor/machinery/telecomms.dm
deleted file mode 100644
index 1068cfb0b4e..00000000000
--- a/code/game/objects/structures/decor/machinery/telecomms.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-/obj/structure/decor/machinery/telecomms/processor
- name = "Processor Unit"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "processor"
- desc = "This machine is used to process large quantities of information."
-
-/obj/structure/decor/machinery/telecomms/hub
- name = "Telecommunication Hub"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "hub"
- desc = "A mighty piece of hardware used to send/receive massive amounts of data."
-
-/obj/structure/decor/machinery/telecomms/server
- name = "Telecommunication Server"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "comm_server"
- desc = "A machine used to store data and network statistics."
-
-/obj/structure/decor/machinery/telecomms/relay
- name = "Telecommunication Relay"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "relay"
- desc = "A mighty piece of hardware used to send massive amounts of data far away."
diff --git a/code/game/objects/structures/depot.dm b/code/game/objects/structures/depot.dm
index e970ac911dc..11eb03c94c5 100644
--- a/code/game/objects/structures/depot.dm
+++ b/code/game/objects/structures/depot.dm
@@ -79,7 +79,6 @@
var/beepsound = 'sound/items/timer.ogg'
var/deliberate = FALSE
var/max_cycles = 10
- var/max_fire_range = 9
var/area/syndicate_depot/core/depotarea
/obj/effect/overload/New()
@@ -101,10 +100,6 @@
if(!deliberate)
playsound(loc, beepsound, 50, 0)
cycles++
- var/fire_range = min(cycles, max_fire_range)
-
- for(var/turf/simulated/turf in range(fire_range, T))
- new /obj/effect/hotspot(turf)
return
if(!istype(depotarea))
diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm
index 878b03436ff..4531613610e 100644
--- a/code/game/objects/structures/dresser.dm
+++ b/code/game/objects/structures/dresser.dm
@@ -56,7 +56,7 @@
/obj/structure/dresser/crowbar_act(mob/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
TOOL_ATTEMPT_DISMANTLE_MESSAGE
if(I.use_tool(src, user, 50, volume = I.tool_volume))
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 2dc0cf415cc..cd7b3525478 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -17,11 +17,11 @@
var/opened = 0
var/material_drop = /obj/item/stack/sheet/metal
-/obj/structure/extinguisher_cabinet/New(turf/loc, ndir = null)
+/obj/structure/extinguisher_cabinet/New(turf/loc, direction = null)
..()
- if(ndir)
- pixel_x = (ndir & EAST|WEST) ? (ndir == EAST ? 28 : -28) : 0
- pixel_y = (ndir & NORTH|SOUTH)? (ndir == WEST ? 28 : -28) : 0
+ if(direction)
+ setDir(direction)
+ set_pixel_offsets_from_dir(28, -28, 30, -30)
switch(extinguishertype)
if(NO_EXTINGUISHER)
return
@@ -165,9 +165,8 @@
else
icon_state = "extinguisher_empty"
-/obj/structure/extinguisher_cabinet/empty/New(turf/loc, ndir = null)
+/obj/structure/extinguisher_cabinet/empty
extinguishertype = NO_EXTINGUISHER
- ..()
#undef NO_EXTINGUISHER
#undef NORMAL_EXTINGUISHER
diff --git a/code/game/objects/structures/foodcart.dm b/code/game/objects/structures/foodcart.dm
index 198dbf5f195..3a9a3414986 100644
--- a/code/game/objects/structures/foodcart.dm
+++ b/code/game/objects/structures/foodcart.dm
@@ -40,7 +40,7 @@
food_slots[s]=I
update_icon()
success = 1
- break;
+ break
if(!success)
to_chat(user, fail_msg)
else if(istype(I, /obj/item/reagent_containers/food/drinks))
@@ -51,7 +51,7 @@
drink_slots[s]=I
update_icon()
success = 1
- break;
+ break
if(!success)
to_chat(user, fail_msg)
else if(istype(I, /obj/item/wrench))
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index dcb74369d72..6d27b21e686 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -76,14 +76,14 @@
if(istype(W,/obj/item/stack/rods))
var/obj/item/stack/rods/S = W
if(state == GIRDER_DISPLACED)
- if(S.get_amount() < 2)
- to_chat(user, "You need at least two rods to create a false wall!")
+ if(S.get_amount() < 5)
+ to_chat(user, "You need at least five rods to create a false wall!")
return
to_chat(user, "You start building a reinforced false wall...")
if(do_after(user, 20, target = src))
- if(!loc || !S || S.get_amount() < 2)
+ if(!loc || !S || S.get_amount() < 5)
return
- S.use(2)
+ S.use(5)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/iron/FW = new (loc)
transfer_fingerprints_to(FW)
@@ -374,7 +374,7 @@
/obj/structure/girder/CanAStarPass(ID, dir, caller)
. = !density
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSGRILLE)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 755d2a3de1b..72acf72f613 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -111,7 +111,7 @@
/obj/structure/grille/CanAStarPass(ID, dir, caller)
. = !density
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSGRILLE)
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 21af7f6e615..c3f36e42f1d 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -69,9 +69,9 @@
if(isliving(G.affecting))
if(!has_buckled_mobs())
if(do_mob(user, src, 120))
- if(spike(G.affecting))
- G.affecting.visible_message("[user] slams [G.affecting] onto the meat spike!", "[user] slams you onto the meat spike!", "You hear a squishy wet noise.")
- qdel(G)
+ var/mob/living/affected = G.affecting
+ if(spike(affected))
+ affected.visible_message("[user] slams [affected] onto the meat spike!", "[user] slams you onto the meat spike!", "You hear a squishy wet noise.")
return
return ..()
@@ -130,16 +130,18 @@
release_mob(M)
/obj/structure/kitchenspike/proc/release_mob(mob/living/M)
- var/matrix/m180 = matrix(M.transform)
- m180.Turn(180)
- animate(M, transform = m180, time = 3)
- M.pixel_y = M.get_standard_pixel_y_offset(180)
M.adjustBruteLoss(30)
src.visible_message(text("[M] falls free of [src]!"))
unbuckle_mob(M, force = TRUE)
M.emote("scream")
M.AdjustWeakened(10)
+/obj/structure/kitchenspike/post_unbuckle_mob(mob/living/M)
+ M.pixel_y = M.get_standard_pixel_y_offset(0)
+ var/matrix/m180 = matrix(M.transform)
+ m180.Turn(180)
+ animate(M, transform = m180, time = 3)
+
/obj/structure/kitchenspike/Destroy()
if(has_buckled_mobs())
for(var/mob/living/L in buckled_mobs)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index aae2295e18f..c657e0056e8 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -131,7 +131,7 @@
AC.ui_interact(user)
if("Voice")
- var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav")
+ var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav", "Mute")
var/voice_mutation
switch(voice_choice)
if("Comic Sans")
@@ -142,6 +142,8 @@
voice_mutation = GLOB.swedeblock
if("Chav")
voice_mutation = GLOB.chavblock
+ if("Mute")
+ voice_mutation = GLOB.muteblock
if(voice_mutation)
if(H.dna.GetSEState(voice_mutation))
H.dna.SetSEState(voice_mutation, FALSE)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 1ea1c277af8..5849d96a158 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -232,7 +232,7 @@
/obj/structure/tray/m_tray/CanAStarPass(ID, dir, caller)
. = !density
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSTABLE)
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index b67bc2c70d1..e659bbeedd9 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY(safes)
var/number_of_tumblers = 3 // The amount of tumblers that will be generated.
var/list/tumblers = list() // The list of tumbler dial positions that need to be hit.
- var/list/current_tumbler_index = 1 // The index in the tumblers list of the tumbler dial position that needs to be hit.
+ var/current_tumbler_index = 1 // The index in the tumblers list of the tumbler dial position that needs to be hit.
var/space = 0 // The combined w_class of everything in the safe.
var/maxspace = 24 // The maximum combined w_class of stuff in the safe.
@@ -246,7 +246,7 @@ GLOBAL_LIST_EMPTY(safes)
var/ticks = text2num(href_list["turnright"])
for(var/i = 1 to ticks)
- dial = Wrap(dial - 1, 0, 100)
+ dial = WRAP(dial - 1, 0, 100)
var/invalid_turn = current_tumbler_index % 2 == 0 || current_tumbler_index > number_of_tumblers
if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
@@ -274,7 +274,7 @@ GLOBAL_LIST_EMPTY(safes)
var/ticks = text2num(href_list["turnleft"])
for(var/i = 1 to ticks)
- dial = Wrap(dial + 1, 0, 100)
+ dial = WRAP(dial + 1, 0, 100)
var/invalid_turn = current_tumbler_index % 2 != 0 || current_tumbler_index > number_of_tumblers
if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
@@ -373,6 +373,7 @@ GLOBAL_LIST_EMPTY(safes)
info = "
Safe Codes
"
/obj/item/paper/safe_code/Initialize(mapload)
+ ..()
return INITIALIZE_HINT_LATELOAD
/obj/item/paper/safe_code/LateInitialize(mapload)
diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm
index 3f5d667a356..ba5258004a0 100644
--- a/code/game/objects/structures/signs.dm
+++ b/code/game/objects/structures/signs.dm
@@ -169,7 +169,7 @@
/obj/structure/sign/kiddieplaque
name = "AI developers plaque"
- desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"."
+ desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child's eyes are crossed, and is drooling. Beneath the image, someone has scratched the word \"PACKETS\"."
icon_state = "kiddieplaque"
/obj/structure/sign/atmosplaque
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index 80fd69597c4..22449bb547b 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -288,6 +288,28 @@
return
setDir(turn(dir, 90))
+/obj/structure/statue/kidanstatue
+ name = "Obsidian Kidan warrior statue"
+ desc = "A beautifully carved and menacing statue of a Kidan warrior made out of obsidian. It looks very heavy."
+ icon_state = "kidan"
+ anchored = TRUE
+ oreAmount = 0
+
+/obj/structure/statue/chickenstatue
+ name = "Bronze Chickenman Statue"
+ desc = "An antique and oriental-looking statue of a Chickenman made of bronze."
+ icon_state = "chicken"
+ anchored = TRUE
+ oreAmount = 0
+
+/obj/structure/statue/russian_mulebot
+ desc = "Like a MULEbot, but more Russian and less functional.";
+ icon = 'icons/obj/aibots.dmi';
+ icon_state = "mulebot0";
+ name = "OXENbot"
+ anchored = TRUE
+ oreAmount = 10
+
////////////////////////////////
/obj/structure/snowman
@@ -320,19 +342,3 @@
..()
qdel(src)
-
-/obj/structure/kidanstatue
- name = "Obsidian Kidan warrior statue"
- desc = "A beautifully carved and menacing statue of a Kidan warrior made out of obsidian. It looks very heavy."
- icon = 'icons/obj/decorations.dmi'
- icon_state = "kidanstatue"
- anchored = 1
- density = 1
-
-/obj/structure/chickenstatue
- name = "Bronze Chickenman Statue"
- desc = "An antique and oriental-looking statue of a Chickenman made of bronze."
- icon = 'icons/obj/decorations.dmi'
- icon_state = "chickenstatue"
- anchored = 1
- density = 1
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 5acd4f7d8a3..bdab5ca2466 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -128,7 +128,7 @@
/obj/structure/table/CanAStarPass(ID, dir, caller)
. = !density
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSTABLE)
@@ -224,8 +224,8 @@
if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
return
//Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
- I.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
- I.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
+ I.pixel_x = clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
+ I.pixel_y = clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
item_placed(I)
else
return ..()
@@ -666,7 +666,7 @@
/obj/structure/rack/CanAStarPass(ID, dir, caller)
. = !density
- if(ismovableatom(caller))
+ if(ismovable(caller))
var/atom/movable/mover = caller
. = . || mover.checkpass(PASSTABLE)
diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm
index 854bc18ce00..692d15d79ec 100644
--- a/code/game/objects/structures/tank_dispenser.dm
+++ b/code/game/objects/structures/tank_dispenser.dm
@@ -1,3 +1,5 @@
+#define MAX_TANK_STORAGE 10
+
/obj/structure/dispenser
name = "tank storage unit"
desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten plasma tanks."
@@ -5,29 +7,51 @@
icon_state = "dispenser"
density = 1
anchored = 1.0
- var/oxygentanks = 10
- var/plasmatanks = 10
- var/list/oxytanks = list() //sorry for the similar var names
- var/list/platanks = list()
+ var/starting_oxygen_tanks = MAX_TANK_STORAGE // The starting amount of oxygen tanks the dispenser gets when it's spawned
+ var/starting_plasma_tanks = MAX_TANK_STORAGE // Starting amount of plasma tanks
+ var/list/stored_oxygen_tanks = list() // List of currently stored oxygen tanks
+ var/list/stored_plasma_tanks = list() // And plasma tanks
/obj/structure/dispenser/oxygen
- plasmatanks = 0
+ starting_plasma_tanks = 0
/obj/structure/dispenser/plasma
- oxygentanks = 0
+ starting_oxygen_tanks = 0
/obj/structure/dispenser/New()
..()
+ initialize_tanks()
update_icon()
+/obj/structure/dispenser/Destroy()
+ QDEL_LIST(stored_plasma_tanks)
+ QDEL_LIST(stored_oxygen_tanks)
+ return ..()
+
+/obj/structure/dispenser/proc/initialize_tanks()
+ for(var/I in 1 to starting_plasma_tanks)
+ var/obj/item/tank/plasma/P = new(src)
+ stored_plasma_tanks.Add(P)
+
+ for(var/I in 1 to starting_oxygen_tanks)
+ var/obj/item/tank/oxygen/O = new(src)
+ stored_oxygen_tanks.Add(O)
+
/obj/structure/dispenser/update_icon()
- overlays.Cut()
- switch(oxygentanks)
- if(1 to 3) overlays += "oxygen-[oxygentanks]"
- if(4 to INFINITY) overlays += "oxygen-4"
- switch(plasmatanks)
- if(1 to 4) overlays += "plasma-[plasmatanks]"
- if(5 to INFINITY) overlays += "plasma-5"
+ cut_overlays()
+ var/oxy_tank_amount = LAZYLEN(stored_oxygen_tanks)
+ switch(oxy_tank_amount)
+ if(1 to 3)
+ overlays += "oxygen-[oxy_tank_amount]"
+ if(4 to INFINITY)
+ overlays += "oxygen-4"
+
+ var/pla_tank_amount = LAZYLEN(stored_plasma_tanks)
+ switch(pla_tank_amount)
+ if(1 to 4)
+ overlays += "plasma-[pla_tank_amount]"
+ if(5 to INFINITY)
+ overlays += "plasma-5"
/obj/structure/dispenser/attack_hand(mob/user)
if(..())
@@ -38,7 +62,7 @@
/obj/structure/dispenser/attack_ghost(mob/user)
ui_interact(user)
-/obj/structure/dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
+/obj/structure/dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, master_ui = null, datum/topic_state/state = GLOB.default_state)
user.set_machine(src)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -47,35 +71,19 @@
/obj/structure/dispenser/ui_data(user)
var/list/data = list()
- data["o_tanks"] = oxygentanks
- data["p_tanks"] = plasmatanks
+ data["o_tanks"] = LAZYLEN(stored_oxygen_tanks)
+ data["p_tanks"] = LAZYLEN(stored_plasma_tanks)
return data
/obj/structure/dispenser/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/tank/oxygen) || istype(I, /obj/item/tank/air) || istype(I, /obj/item/tank/anesthetic))
- if(oxygentanks < 10)
- user.drop_item()
- I.forceMove(src)
- oxytanks.Add(I)
- oxygentanks++
- update_icon()
- to_chat(user, "You put [I] in [src].")
- else
- to_chat(user, "[src] is full.")
- SSnanoui.update_uis(src)
+ try_insert_tank(user, stored_oxygen_tanks, I)
return
+
if(istype(I, /obj/item/tank/plasma))
- if(plasmatanks < 10)
- user.drop_item()
- I.forceMove(src)
- platanks.Add(I)
- plasmatanks++
- update_icon()
- to_chat(user, "You put [I] in [src].")
- else
- to_chat(user, "[src] is full.")
- SSnanoui.update_uis(src)
+ try_insert_tank(user, stored_plasma_tanks, I)
return
+
if(istype(I, /obj/item/wrench))
if(anchored)
to_chat(user, "You lean down and unwrench [src].")
@@ -88,40 +96,55 @@
/obj/structure/dispenser/Topic(href, href_list)
if(..())
- return 1
+ return TRUE
if(Adjacent(usr))
usr.set_machine(src)
+
+ // The oxygen tank button
if(href_list["oxygen"])
- if(oxygentanks > 0)
- var/obj/item/tank/oxygen/O
- if(oxytanks.len == oxygentanks)
- O = oxytanks[1]
- oxytanks.Remove(O)
- else
- O = new /obj/item/tank/oxygen(loc)
- O.loc = loc
- to_chat(usr, "You take [O] out of [src].")
- oxygentanks--
- update_icon()
+ try_remove_tank(usr, stored_oxygen_tanks)
+
+ // The plasma tank button
if(href_list["plasma"])
- if(plasmatanks > 0)
- var/obj/item/tank/plasma/P
- if(platanks.len == plasmatanks)
- P = platanks[1]
- platanks.Remove(P)
- else
- P = new /obj/item/tank/plasma(loc)
- P.loc = loc
- to_chat(usr, "You take [P] out of [src].")
- plasmatanks--
- update_icon()
+ try_remove_tank(usr, stored_plasma_tanks)
+
add_fingerprint(usr)
updateUsrDialog()
- SSnanoui.update_uis(src)
+ SSnanoui.try_update_ui(usr, src)
else
SSnanoui.close_user_uis(usr,src)
- return 1
+ return TRUE
+
+/// Called when the user clicks on the oxygen or plasma tank UI buttons, and tries to withdraw a tank.
+/obj/structure/dispenser/proc/try_remove_tank(mob/living/user, list/tank_list)
+ if(!LAZYLEN(tank_list))
+ return // There are no tanks left to withdraw.
+
+ var/obj/item/tank/T = tank_list[1]
+ tank_list.Remove(T)
+
+ if(!user.put_in_hands(T))
+ T.forceMove(loc) // If the user's hands are full, place it on the tile of the dispenser.
+
+ to_chat(user, "You take [T] out of [src].")
+ update_icon()
+
+/// Called when the user clicks on the dispenser with a tank. Tries to insert the tank into the dispenser, and updates the UI if successful.
+/obj/structure/dispenser/proc/try_insert_tank(mob/living/user, list/tank_list, obj/item/tank/T)
+ if(LAZYLEN(tank_list) >= MAX_TANK_STORAGE)
+ to_chat(user, "[src] is full.")
+ return
+
+ if(!user.drop_item()) // Antidrop check
+ to_chat(user, "[T] is stuck to your hand!")
+ return
+
+ T.forceMove(src)
+ tank_list.Add(T)
+ update_icon()
+ to_chat(user, "You put [T] in [src].")
+ SSnanoui.try_update_ui(user, src)
/obj/structure/tank_dispenser/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
@@ -130,3 +153,5 @@
I.forceMove(loc)
new /obj/item/stack/sheet/metal(loc, 2)
qdel(src)
+
+#undef MAX_TANK_STORAGE
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index f8f406d1381..9d06f870fc3 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -38,7 +38,7 @@
if(pod.contents.len)
to_chat(AM, "")
return
- else if(!pod.moving && pod.dir in directions())
+ else if(!pod.moving && (pod.dir in directions()))
AM.forceMove(pod)
return
@@ -47,7 +47,7 @@
/obj/structure/transit_tube/station/attack_hand(mob/user as mob)
if(!pod_moving)
for(var/obj/structure/transit_tube_pod/pod in loc)
- if(!pod.moving && pod.dir in directions())
+ if(!pod.moving && (pod.dir in directions()))
if(icon_state == "closed")
open_animation()
@@ -100,7 +100,7 @@
/obj/structure/transit_tube/station/proc/launch_pod()
for(var/obj/structure/transit_tube_pod/pod in loc)
- if(!pod.moving && pod.dir in directions())
+ if(!pod.moving && (pod.dir in directions()))
spawn(5)
pod_moving = 1
close_animation()
diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
index 7095fd4eeda..8984dc60a52 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
@@ -144,9 +144,7 @@
if(istype(mob, /mob) && mob.client)
// If the pod is not in a tube at all, you can get out at any time.
if(!(locate(/obj/structure/transit_tube) in loc))
- mob.loc = loc
- mob.client.Move(get_step(loc, direction), direction)
- mob.reset_perspective(null)
+ mob.forceMove(loc)
//if(moving && istype(loc, /turf/space))
// Todo: If you get out of a moving pod in space, you should move as well.
@@ -158,9 +156,7 @@
if(!station.pod_moving)
if(direction == station.dir)
if(station.icon_state == "open")
- mob.loc = loc
- mob.client.Move(get_step(loc, direction), direction)
- mob.reset_perspective(null)
+ mob.forceMove(loc)
else
station.open_animation()
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index a529dc3a6e7..1a5b275bc01 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -403,75 +403,7 @@
L.ExtinguishMob()
L.adjust_fire_stacks(-20) //Douse ourselves with water to avoid fire more easily
to_chat(L, "You've been drenched in water!")
- if(iscarbon(O))
- var/mob/living/carbon/M = O
- if(M.r_hand)
- M.r_hand.clean_blood()
- if(M.l_hand)
- M.l_hand.clean_blood()
- if(M.back)
- if(M.back.clean_blood())
- M.update_inv_back(0)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- var/washgloves = 1
- var/washshoes = 1
- var/washmask = 1
- var/washears = 1
- var/washglasses = 1
-
- if(H.wear_suit)
- washgloves = !(H.wear_suit.flags_inv & HIDEGLOVES)
- washshoes = !(H.wear_suit.flags_inv & HIDESHOES)
-
- if(H.head)
- washmask = !(H.head.flags_inv & HIDEMASK)
- washglasses = !(H.head.flags_inv & HIDEEYES)
- washears = !(H.head.flags_inv & HIDEEARS)
-
- if(H.wear_mask)
- if(washears)
- washears = !(H.wear_mask.flags_inv & HIDEEARS)
- if(washglasses)
- washglasses = !(H.wear_mask.flags_inv & HIDEEYES)
-
- if(H.head)
- if(H.head.clean_blood())
- H.update_inv_head(0,0)
- if(H.wear_suit)
- if(H.wear_suit.clean_blood())
- H.update_inv_wear_suit(0,0)
- else if(H.w_uniform)
- if(H.w_uniform.clean_blood())
- H.update_inv_w_uniform(0,0)
- if(H.gloves && washgloves)
- if(H.gloves.clean_blood())
- H.update_inv_gloves(0,0)
- if(H.shoes && washshoes)
- if(H.shoes.clean_blood())
- H.update_inv_shoes(0,0)
- if(H.wear_mask && washmask)
- if(H.wear_mask.clean_blood())
- H.update_inv_wear_mask(0)
- if(H.glasses && washglasses)
- if(H.glasses.clean_blood())
- H.update_inv_glasses(0)
- if(H.l_ear && washears)
- if(H.l_ear.clean_blood())
- H.update_inv_ears(0)
- if(H.r_ear && washears)
- if(H.r_ear.clean_blood())
- H.update_inv_ears(0)
- if(H.belt)
- if(H.belt.clean_blood())
- H.update_inv_belt(0)
- else
- if(M.wear_mask) //if the mob is not human, it cleans the mask without asking for bitflags
- if(M.wear_mask.clean_blood())
- M.update_inv_wear_mask(0)
-
- else
- O.clean_blood()
+ L.clean_blood()
if(isturf(loc))
var/turf/tile = loc
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 8fe46ca052d..9faab45cf97 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -254,7 +254,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(!can_be_reached(user))
return
to_chat(user, "You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...")
- if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
+ if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
return
state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME)
to_chat(user, "You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.")
@@ -268,20 +268,20 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(reinf)
if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME)
to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...")
- if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
+ if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
return
state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME)
to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.")
else if(state == WINDOW_OUT_OF_FRAME)
to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...")
- if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
+ if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
return
anchored = !anchored
update_nearby_icons()
to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.")
else //if we're not reinforced, we don't need to check or update state
to_chat(user, "You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...")
- if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_anchored, anchored))))
+ if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_anchored, anchored)))
return
anchored = !anchored
air_update_turf(TRUE)
@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(!can_be_reached(user))
return
TOOL_ATTEMPT_DISMANTLE_MESSAGE
- if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
+ if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
return
var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount)
G.add_fingerprint(user)
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index 6c10921e6bd..6bc1c4ba142 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -8,12 +8,6 @@
nitrogen = MOLES_N2STANDARD
var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
- var/dirtoverlay = null
-
-/turf/simulated/New()
- ..()
- levelupdate()
- visibilityChanged()
/turf/simulated/proc/break_tile()
return
@@ -35,7 +29,12 @@
assume_air(lowertemp)
qdel(hotspot)
-/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER, infinite = FALSE) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost
+/*
+ * Makes a turf slippery using the given parameters
+ * @param wet_setting The type of slipperyness used
+ * @param time Time the turf is slippery. If null it will pick a random time between 790 and 820 ticks. If INFINITY then it won't dry up ever
+*/
+/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER, time = null) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost
if(wet >= wet_setting)
return
wet = wet_setting
@@ -55,13 +54,13 @@
else
wet_overlay = image('icons/effects/water.dmi', src, "wet_static")
overlays += wet_overlay
- if(!infinite)
- spawn(rand(790, 820)) // Purely so for visual effect
- if(!istype(src, /turf/simulated)) //Because turfs don't get deleted, they change, adapt, transform, evolve and deform. they are one and they are all.
- return
- MakeDry(wet_setting)
+ if(time == INFINITY)
+ return
+ if(!time)
+ time = rand(790, 820)
+ addtimer(CALLBACK(src, .proc/MakeDry, wet_setting), time)
-/turf/simulated/proc/MakeDry(wet_setting = TURF_WET_WATER)
+/turf/simulated/MakeDry(wet_setting = TURF_WET_WATER)
if(wet > wet_setting)
return
wet = TURF_DRY
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index e425c3458c3..614b8232b0b 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -27,24 +27,16 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
var/burnt = 0
var/current_overlay = null
var/floor_tile = null //tile that this floor drops
- var/obj/item/stack/tile/builtin_tile = null //needed for performance reasons when the singularity rips off floor tiles
var/list/broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
var/list/burnt_states = list("floorscorched1", "floorscorched2")
var/list/prying_tool_list = list(TOOL_CROWBAR) //What tool/s can we use to pry up the tile?
-/turf/simulated/floor/New()
- ..()
+/turf/simulated/floor/Initialize(mapload)
+ . = ..()
if(icon_state in GLOB.icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default
icon_regular_floor = "floor"
else
icon_regular_floor = icon_state
- if(floor_tile)
- builtin_tile = new floor_tile
-
-/turf/simulated/floor/Destroy()
- QDEL_NULL(builtin_tile)
- return ..()
-
//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=0)
// if((istype(mover, /obj/machinery/vehicle) && !(src.burnt)))
@@ -187,7 +179,7 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
if(T.turf_type == type)
return
var/obj/item/thing = user.get_inactive_hand()
- if(!prying_tool_list.Find(thing.tool_behaviour))
+ if(!thing || !prying_tool_list.Find(thing.tool_behaviour))
return
var/turf/simulated/floor/plating/P = pry_tile(thing, user, TRUE)
if(!istype(P))
@@ -209,30 +201,26 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
else
if(user && !silent)
to_chat(user, "You remove the floor tile.")
- if(builtin_tile && make_tile)
- builtin_tile.forceMove(src)
- builtin_tile = null
+ if(floor_tile && make_tile)
+ new floor_tile(src)
return make_plating()
/turf/simulated/floor/singularity_pull(S, current_size)
..()
if(current_size == STAGE_THREE)
if(prob(30))
- if(builtin_tile)
- builtin_tile.loc = src
- builtin_tile = null
+ if(floor_tile)
+ new floor_tile(src)
make_plating()
else if(current_size == STAGE_FOUR)
if(prob(50))
- if(builtin_tile)
- builtin_tile.loc = src
- builtin_tile = null
+ if(floor_tile)
+ new floor_tile(src)
make_plating()
else if(current_size >= STAGE_FIVE)
- if(builtin_tile)
+ if(floor_tile)
if(prob(70))
- builtin_tile.loc = src
- builtin_tile = null
+ new floor_tile(src)
make_plating()
else if(prob(50))
ReplaceWithLattice()
diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm
index 6d5d95dff0e..6118885a921 100644
--- a/code/game/turfs/simulated/floor/asteroid.dm
+++ b/code/game/turfs/simulated/floor/asteroid.dm
@@ -227,7 +227,7 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me
break
var/list/L = list(45)
- if(IsOdd(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
+ if(ISODD(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
L += -45
// Expand the edges of our tunnel
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index 3ab424e69cc..bfbfa70331e 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -31,9 +31,8 @@
if(make_tile)
if(user && !silent)
to_chat(user, "You unscrew the planks.")
- if(builtin_tile)
- builtin_tile.forceMove(src)
- builtin_tile = null
+ if(floor_tile)
+ new floor_tile(src)
else
if(user && !silent)
to_chat(user, "You forcefully pry off the planks, destroying them in the process.")
@@ -50,9 +49,9 @@
floor_tile = /obj/item/stack/tile/grass
broken_states = list("sand")
-/turf/simulated/floor/grass/Initialize()
+/turf/simulated/floor/grass/Initialize(mapload)
+ . = ..()
update_icon()
- ..()
/turf/simulated/floor/grass/update_icon()
icon_state = "grass[pick("1","2","3","4")]"
@@ -81,10 +80,9 @@
)
-/turf/simulated/floor/carpet/New()
- ..()
- if(broken || burnt)
- make_plating()
+/turf/simulated/floor/carpet/Initialize(mapload)
+ . = ..()
+ update_icon()
/turf/simulated/floor/carpet/update_icon()
if(!..())
@@ -120,18 +118,18 @@
broken_states = list("damaged")
plane = PLANE_SPACE
-/turf/simulated/floor/fakespace/New()
- ..()
- icon_state = "[rand(0,25)]"
-
-/turf/simulated/floor/carpet/arcade
- icon = 'icons/goonstation/turf/floor.dmi'
- icon_state = "arcade"
- floor_tile = /obj/item/stack/tile/arcade_carpet
- smooth = SMOOTH_FALSE
+/turf/simulated/floor/fakespace/Initialize(mapload)
+ . = ..()
+ icon_state = SPACE_ICON_STATE
/turf/simulated/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
return TRUE
+
+/turf/simulated/floor/carpet/arcade
+ icon = 'icons/goonstation/turf/floor.dmi'
+ icon_state = "arcade"
+ floor_tile = /obj/item/stack/tile/arcade_carpet
+ smooth = SMOOTH_FALSE
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
index f231a4fd0b3..4f551fb485a 100644
--- a/code/game/turfs/simulated/floor/indestructible.dm
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -45,6 +45,7 @@
oxygen = 14
nitrogen = 23
temperature = 300
+ planetary_atmos = TRUE
/turf/simulated/floor/indestructible/necropolis/Initialize(mapload)
. = ..()
@@ -52,8 +53,8 @@
icon_state = "necro[rand(2,3)]"
/turf/simulated/floor/indestructible/necropolis/air
- oxygen = 0
- nitrogen = 0
+ oxygen = MOLES_O2STANDARD
+ nitrogen = MOLES_N2STANDARD
temperature = T20C
/turf/simulated/floor/indestructible/boss //you put stone tiles on this and use it as a base
@@ -64,6 +65,7 @@
oxygen = 14
nitrogen = 23
temperature = 300
+ planetary_atmos = TRUE
/turf/simulated/floor/indestructible/boss/air
oxygen = MOLES_O2STANDARD
@@ -77,6 +79,7 @@
oxygen = 14
nitrogen = 23
temperature = 300
+ planetary_atmos = TRUE
smooth = SMOOTH_TRUE
/turf/simulated/floor/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm
index 57e90840920..14a08639132 100644
--- a/code/game/turfs/simulated/floor/lava.dm
+++ b/code/game/turfs/simulated/floor/lava.dm
@@ -8,9 +8,6 @@
light_power = 0.75
light_color = LIGHT_COLOR_LAVA
-/turf/simulated/floor/plating/lava/New()
- ..()
-
/turf/simulated/floor/plating/lava/ex_act()
return
@@ -80,8 +77,8 @@
O.resistance_flags |= FLAMMABLE //Even fireproof things burn up in lava
if(O.resistance_flags & FIRE_PROOF)
O.resistance_flags &= ~FIRE_PROOF
- if(O.armor["fire"] > 50) //obj with 100% fire armor still get slowly burned away.
- O.armor["fire"] = 50
+ if(O.armor.getRating("fire") > 50) //obj with 100% fire armor still get slowly burned away.
+ O.armor = O.armor.setRating(fire_value = 50)
O.fire_act(10000, 1000)
else if(isliving(thing))
@@ -113,6 +110,9 @@
/turf/simulated/floor/plating/lava/attackby(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on
return
+/turf/simulated/floor/plating/lava/screwdriver_act()
+ return
+
/turf/simulated/floor/plating/lava/welder_act()
return
diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm
index 332cf745a4c..8276c0de33f 100644
--- a/code/game/turfs/simulated/floor/light_floor.dm
+++ b/code/game/turfs/simulated/floor/light_floor.dm
@@ -20,8 +20,8 @@
var/state = LIGHTFLOOR_ON
var/can_modify_colour = TRUE
-/turf/simulated/floor/light/New()
- ..()
+/turf/simulated/floor/light/Initialize(mapload)
+ . = ..()
update_icon()
/turf/simulated/floor/light/update_icon()
@@ -77,14 +77,13 @@
/turf/simulated/floor/light/attackby(obj/item/C, mob/user, params)
if(istype(C,/obj/item/light/bulb)) //only for light tiles
- if(istype(builtin_tile, /obj/item/stack/tile/light))
- if(!state)
- qdel(C)
- state = LIGHTFLOOR_ON
- update_icon()
- to_chat(user, "You replace the light bulb.")
- else
- to_chat(user, "The light bulb seems fine, no need to replace it.")
+ if(!state)
+ qdel(C)
+ state = LIGHTFLOOR_ON
+ update_icon()
+ to_chat(user, "You replace the light bulb.")
+ else
+ to_chat(user, "The light bulb seems fine, no need to replace it.")
else
return ..()
diff --git a/code/game/turfs/simulated/floor/mineral.dm b/code/game/turfs/simulated/floor/mineral.dm
index 5eb387abbae..dd975dc80d9 100644
--- a/code/game/turfs/simulated/floor/mineral.dm
+++ b/code/game/turfs/simulated/floor/mineral.dm
@@ -14,8 +14,8 @@
icon_state = ""
var/list/icons = list()
-/turf/simulated/floor/mineral/New()
- ..()
+/turf/simulated/floor/mineral/Initialize(mapload)
+ . = ..()
broken_states = list("[initial(icon_state)]_dam")
/turf/simulated/floor/mineral/update_icon()
@@ -97,24 +97,24 @@
broken_states = list("titanium_dam1","titanium_dam2","titanium_dam3","titanium_dam4","titanium_dam5")
/turf/simulated/floor/mineral/titanium/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/turf/simulated/floor/mineral/titanium/blue
icon_state = "titanium_blue"
/turf/simulated/floor/mineral/titanium/blue/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/turf/simulated/floor/mineral/titanium/yellow
icon_state = "titanium_yellow"
/turf/simulated/floor/mineral/titanium/yellow/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/turf/simulated/floor/mineral/titanium/purple
@@ -122,8 +122,8 @@
floor_tile = /obj/item/stack/tile/mineral/titanium/purple
/turf/simulated/floor/mineral/titanium/purple/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
//PLASTITANIUM (syndieshuttle)
@@ -137,8 +137,8 @@
icon_state = "plastitanium_red"
/turf/simulated/floor/mineral/plastitanium/red/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/turf/simulated/floor/mineral/plastitanium/red/brig
@@ -179,14 +179,14 @@
spam_flag = world.time + 10
/turf/simulated/floor/mineral/bananium/airless
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
/turf/simulated/floor/mineral/bananium/lubed/Initialize(mapload)
. = ..()
- MakeSlippery(TURF_WET_LUBE, TRUE)
+ MakeSlippery(TURF_WET_LUBE, INFINITY)
/turf/simulated/floor/mineral/bananium/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride
if(ishuman(user))
@@ -254,8 +254,8 @@
floor_tile = /obj/item/stack/tile/mineral/abductor
icons = list("alienpod1", "alienpod2", "alienpod3", "alienpod4", "alienpod5", "alienpod6", "alienpod7", "alienpod8", "alienpod9")
-/turf/simulated/floor/mineral/abductor/New()
- ..()
+/turf/simulated/floor/mineral/abductor/Initialize(mapload)
+ . = ..()
icon_state = "alienpod[rand(1,9)]"
/turf/simulated/floor/mineral/abductor/break_tile()
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index 33ae636090d..0808fef7e95 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -3,23 +3,23 @@
icon_state = "rockvault"
smooth = SMOOTH_FALSE
-/turf/simulated/floor/vault/New(location, vtype)
- ..()
- icon_state = "[vtype]vault"
-
/turf/simulated/wall/vault
icon = 'icons/turf/walls.dmi'
icon_state = "rockvault"
smooth = SMOOTH_FALSE
-/turf/simulated/wall/vault/New(location, vtype)
- ..()
- icon_state = "[vtype]vault"
-
/turf/simulated/floor/bluegrid
icon = 'icons/turf/floors.dmi'
icon_state = "bcircuit"
+/turf/simulated/floor/bluegrid/telecomms
+ nitrogen = 100
+ oxygen = 0
+ temperature = 80
+
+/turf/simulated/floor/bluegrid/telecomms/server
+ name = "server base"
+
/turf/simulated/floor/greengrid
icon = 'icons/turf/floors.dmi'
icon_state = "gcircuit"
@@ -27,12 +27,12 @@
/turf/simulated/floor/greengrid/airless
icon_state = "gcircuit"
name = "airless floor"
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
-/turf/simulated/floor/greengrid/airless/New()
- ..()
+/turf/simulated/floor/greengrid/airless/Initialize(mapload)
+ . = ..()
name = "floor"
/turf/simulated/floor/redgrid
@@ -70,8 +70,8 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/obj/machinery/poolcontroller/linkedcontroller = null
-/turf/simulated/floor/beach/water/New()
- ..()
+/turf/simulated/floor/beach/water/Initialize(mapload)
+ . = ..()
var/image/overlay_image = image('icons/misc/beach.dmi', icon_state = "water5", layer = ABOVE_MOB_LAYER)
overlay_image.plane = GAME_PLANE
overlays += overlay_image
@@ -111,6 +111,7 @@
oxygen = 14
nitrogen = 23
temperature = 300
+ planetary_atmos = TRUE
/turf/simulated/floor/lubed
name = "slippery floor"
@@ -118,7 +119,7 @@
/turf/simulated/floor/lubed/Initialize(mapload)
. = ..()
- MakeSlippery(TURF_WET_LUBE, TRUE)
+ MakeSlippery(TURF_WET_LUBE, INFINITY)
/turf/simulated/floor/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride
if(ishuman(user))
diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm
index d36396aaa5f..116d57dc1ef 100644
--- a/code/game/turfs/simulated/floor/plasteel_floor.dm
+++ b/code/game/turfs/simulated/floor/plasteel_floor.dm
@@ -12,12 +12,12 @@
/turf/simulated/floor/plasteel/airless
name = "airless floor"
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
-/turf/simulated/floor/plasteel/airless/New()
- ..()
+/turf/simulated/floor/plasteel/airless/Initialize(mapload)
+ . = ..()
name = "floor"
/turf/simulated/floor/plasteel/airless/indestructible // For bomb testing range
@@ -41,6 +41,11 @@
/turf/simulated/floor/plasteel/dark
icon_state = "darkfull"
+/turf/simulated/floor/plasteel/dark/telecomms
+ nitrogen = 100
+ oxygen = 0
+ temperature = 80
+
/turf/simulated/floor/plasteel/freezer
icon_state = "freezerfloor"
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 85b03d3378d..a6dbe0de281 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -14,17 +14,17 @@
"xeno" = list('sound/effects/footstep/plating_xeno.ogg')
)
-/turf/simulated/floor/plating/New()
- ..()
+/turf/simulated/floor/plating/Initialize(mapload)
+ . = ..()
icon_plating = icon_state
update_icon()
-/turf/simulated/floor/plating/damaged/New()
- ..()
+/turf/simulated/floor/plating/damaged/Initialize(mapload)
+ . = ..()
break_tile()
-/turf/simulated/floor/plating/burnt/New()
- ..()
+/turf/simulated/floor/plating/burnt/Initialize(mapload)
+ . = ..()
burn_tile()
/turf/simulated/floor/plating/update_icon()
@@ -104,7 +104,7 @@
broken = FALSE
update_icon()
-/turf/simulated/floor/plating/proc/remove_plating(mob/user)
+/turf/simulated/floor/plating/remove_plating(mob/user)
if(baseturf == /turf/space)
ReplaceWithLattice()
else
@@ -113,12 +113,12 @@
/turf/simulated/floor/plating/airless
icon_state = "plating"
name = "airless plating"
- oxygen = 0.01
- nitrogen = 0.01
+ oxygen = 0
+ nitrogen = 0
temperature = TCMB
-/turf/simulated/floor/plating/airless/New()
- ..()
+/turf/simulated/floor/plating/airless/Initialize(mapload)
+ . = ..()
name = "plating"
/turf/simulated/floor/engine
@@ -190,8 +190,8 @@
name = "engraved floor"
icon_state = "cult"
-/turf/simulated/floor/engine/cult/New()
- ..()
+/turf/simulated/floor/engine/cult/Initialize(mapload)
+ . = ..()
if(SSticker.mode)//only do this if the round is going..otherwise..fucking asteroid..
icon_state = SSticker.cultdat.cult_floor_icon_state
@@ -205,16 +205,41 @@
color = "#FAE48C"
animate(src, color = previouscolor, time = 8)
-/turf/simulated/floor/engine/n20/New()
- ..()
- var/datum/gas_mixture/adding = new
- var/datum/gas/sleeping_agent/trace_gas = new
+//air filled floors; used in atmos pressure chambers
- trace_gas.moles = 6000
- adding.trace_gases += trace_gas
- adding.temperature = T20C
+/turf/simulated/floor/engine/n20
+ name = "\improper N2O floor"
+ sleeping_agent = 6000
+ oxygen = 0
+ nitrogen = 0
+
+/turf/simulated/floor/engine/co2
+ name = "\improper CO2 floor"
+ carbon_dioxide = 50000
+ oxygen = 0
+ nitrogen = 0
+
+/turf/simulated/floor/engine/plasma
+ name = "plasma floor"
+ toxins = 70000
+ oxygen = 0
+ nitrogen = 0
+
+/turf/simulated/floor/engine/o2
+ name = "\improper O2 floor"
+ oxygen = 100000
+ nitrogen = 0
+
+/turf/simulated/floor/engine/n2
+ name = "\improper N2 floor"
+ nitrogen = 100000
+ oxygen = 0
+
+/turf/simulated/floor/engine/air
+ name = "air floor"
+ oxygen = 2644
+ nitrogen = 10580
- assume_air(adding)
/turf/simulated/floor/engine/singularity_pull(S, current_size)
..()
@@ -250,8 +275,8 @@
icon = 'icons/turf/floors/ironsand.dmi'
icon_state = "ironsand1"
-/turf/simulated/floor/plating/ironsand/New()
- ..()
+/turf/simulated/floor/plating/ironsand/Initialize(mapload)
+ . = ..()
icon_state = "ironsand[rand(1,15)]"
/turf/simulated/floor/plating/ironsand/remove_plating()
@@ -334,8 +359,8 @@
name = "alien floor"
icon_state = "alienpod1"
-/turf/simulated/floor/plating/abductor/New()
- ..()
+/turf/simulated/floor/plating/abductor/Initialize(mapload)
+ . = ..()
icon_state = "alienpod[rand(1,9)]"
/turf/simulated/floor/plating/ice
@@ -353,7 +378,7 @@
/turf/simulated/floor/plating/ice/Initialize(mapload)
. = ..()
- MakeSlippery(TURF_WET_PERMAFROST, TRUE)
+ MakeSlippery(TURF_WET_PERMAFROST, INFINITY)
/turf/simulated/floor/plating/ice/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
return
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index ebad3554f18..8bf3e820d3d 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -439,7 +439,7 @@
var/area/A = get_area(bombturf)
var/notify_admins = 0
- if(z != 5)
+ if(!is_mining_level(z))
notify_admins = 1
if(!triggered_by_explosion)
message_admins("[key_name_admin(user)] has triggered a gibtonite deposit reaction at [A.name] (JMP).")
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 078a1b8e513..23d0c9789bd 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -34,7 +34,6 @@
var/sheet_type = /obj/item/stack/sheet/metal
var/sheet_amount = 2
var/girder_type = /obj/structure/girder
- var/obj/item/stack/sheet/builtin_sheet = null
canSmoothWith = list(
/turf/simulated/wall,
@@ -46,10 +45,6 @@
/turf/simulated/wall/r_wall/coated)
smooth = SMOOTH_TRUE
-/turf/simulated/wall/New()
- ..()
- builtin_sheet = new sheet_type
-
/turf/simulated/wall/BeforeChange()
for(var/obj/effect/overlay/wall_rot/WR in src)
qdel(WR)
@@ -139,7 +134,7 @@
P.setAngle(new_angle_s)
return TRUE
-/turf/simulated/wall/proc/dismantle_wall(devastated = 0, explode = 0)
+/turf/simulated/wall/dismantle_wall(devastated = FALSE, explode = FALSE)
if(devastated)
devastate_wall()
else
@@ -156,6 +151,7 @@
O.forceMove(src)
ChangeTurf(/turf/simulated/floor/plating)
+ return TRUE
/turf/simulated/wall/proc/break_wall()
new sheet_type(src, sheet_amount)
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index bc04a695da7..8b60be916c3 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -277,6 +277,9 @@
/turf/simulated/wall/mineral/titanium/nodecon/burn_down()
return
+/turf/simulated/wall/mineral/titanium/nodecon/welder_act()
+ return
+
/////////////////////Plastitanium walls/////////////////////
/turf/simulated/wall/mineral/plastitanium
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index e43ea15f53f..56908a7ecae 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -3,15 +3,14 @@
desc = "A cold metal wall engraved with indecipherable symbols. Studying them causes your head to pound."
icon = 'icons/turf/walls/cult_wall.dmi'
icon_state = "cult"
- builtin_sheet = null
canSmoothWith = null
smooth = SMOOTH_FALSE
sheet_type = /obj/item/stack/sheet/runed_metal
sheet_amount = 1
girder_type = /obj/structure/girder/cult
-/turf/simulated/wall/cult/New()
- ..()
+/turf/simulated/wall/cult/Initialize(mapload)
+ . = ..()
if(SSticker.mode)//game hasn't started offically don't do shit..
new /obj/effect/temp_visual/cult/turf(src)
icon_state = SSticker.cultdat.cult_wall_icon_state
@@ -73,10 +72,7 @@
realappearance.linked = src
/turf/simulated/wall/clockwork/Destroy()
- if(realappearance)
- qdel(realappearance)
- realappearance = null
-
+ QDEL_NULL(realappearance)
return ..()
/turf/simulated/wall/clockwork/ReplaceWithLattice()
@@ -109,6 +105,7 @@
P.roll_and_drop(src)
else
O.forceMove(src)
+ return TRUE
/turf/simulated/wall/clockwork/devastate_wall()
for(var/i in 1 to 2)
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index 502803bc7d3..a3e9c9ae0f2 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -43,7 +43,7 @@
update_icon()
to_chat(user, "You press firmly on the cover, dislodging it.")
return
- else if(RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter))
+ else if(d_state == RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter))
to_chat(user, "You begin slicing through the support rods...")
if(I.use_tool(src, user, 70, volume = I.tool_volume) && d_state == RWALL_SUPPORT_RODS)
d_state = RWALL_SHEATH
@@ -132,11 +132,11 @@
to_chat(user, "You pry off the cover.")
if(RWALL_SHEATH)
to_chat(user, "You struggle to pry off the outer sheath...")
- if(!I.use_tool(src, user, 100, volume = I.tool_volume) || d_state != RWALL_SHEATH)
+ if(!I.use_tool(src, user, 100, volume = I.tool_volume))
return
- to_chat(user, "You pry off the outer sheath.")
- dismantle_wall()
- return
+ if(dismantle_wall())
+ to_chat(user, "You pry off the outer sheath.")
+
if(RWALL_BOLTS)
to_chat(user, "You start to pry the cover back into place...")
playsound(src, I.usesound, 100, 1)
@@ -199,6 +199,9 @@
to_chat(user, "You tighten the bolts anchoring the support rods.")
update_icon()
+/turf/simulated/wall/r_wall/try_decon(obj/item/I, mob/user, params) //Plasma cutter only works in the deconstruction steps!
+ return FALSE
+
/turf/simulated/wall/r_wall/try_destroy(obj/item/I, mob/user, params)
if(istype(I, /obj/item/pickaxe/drill/diamonddrill))
to_chat(user, "You begin to drill though the wall...")
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index f78f520cfd3..1a8ccdae550 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -21,6 +21,11 @@
/turf/space/Initialize(mapload)
if(!istype(src, /turf/space/transit))
icon_state = SPACE_ICON_STATE
+ vis_contents.Cut() //removes inherited overlays
+
+ if(initialized)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ initialized = TRUE
var/area/A = loc
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
@@ -34,12 +39,6 @@
return INITIALIZE_HINT_NORMAL
-/turf/space/Destroy(force)
- if(force)
- . = ..()
- else
- return QDEL_HINT_LETMELIVE
-
/turf/space/BeforeChange()
..()
var/datum/space_level/S = GLOB.space_manager.get_zlev(z)
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 2a14230d467..dda49fecdbd 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -94,8 +94,6 @@
var/max = world.maxx-TRANSITIONEDGE
var/min = 1+TRANSITIONEDGE
- var/_z = pick(levels_by_trait(REACHABLE)) //select a random space zlevel
-
//now select coordinates for a border turf
var/_x
var/_y
@@ -113,7 +111,8 @@
_x = rand(min,max)
_y = min
- var/turf/T = locate(_x, _y, _z)
+ var/list/levels_available = get_all_linked_levels_zpos()
+ var/turf/T = locate(_x, _y, pick(levels_available))
AM.forceMove(T)
AM.newtonian_move(dir)
@@ -125,9 +124,9 @@
/turf/space/transit/attackby()
return
-/turf/space/transit/New()
+/turf/space/transit/Initialize(mapload)
+ . = ..()
update_icon()
- ..()
/turf/space/transit/proc/update_icon()
var/p = 9
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index caa46b4e245..8f8e7fdca9a 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -3,15 +3,18 @@
level = 1
luminosity = 1
- var/intact = 1
+ var/intact = TRUE
var/turf/baseturf = /turf/space
var/slowdown = 0 //negative for faster, positive for slower
- //Properties for open tiles (/floor)
+ ///Properties for open tiles (/floor)
+ /// All the gas vars, on the turf, are meant to be utilized for initializing a gas datum and setting its first gas values; the turf vars are never further modified at runtime; it is never directly used for calculations by the atmospherics system.
var/oxygen = 0
var/carbon_dioxide = 0
var/nitrogen = 0
var/toxins = 0
+ var/sleeping_agent = 0
+ var/agent_b = 0
//Properties for airtight tiles (/wall)
var/thermal_conductivity = 0.05
@@ -28,21 +31,29 @@
var/image/obscured //camerachunks
+ var/changing_turf = FALSE
+
var/list/blueprint_data //for the station blueprints, images of objects eg: pipes
- var/list/footstep_sounds = list()
+ var/list/footstep_sounds
var/shoe_running_volume = 50
var/shoe_walking_volume = 20
-/turf/New()
- ..()
+/turf/Initialize(mapload)
+ if(initialized)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ initialized = TRUE
+
+ // by default, vis_contents is inherited from the turf that was here before
+ vis_contents.Cut()
+
+ levelupdate()
+ if(smooth)
+ queue_smooth(src)
+ visibilityChanged()
+
for(var/atom/movable/AM in src)
Entered(AM)
- if(smooth && SSticker && SSticker.current_state == GAME_STATE_PLAYING)
- queue_smooth(src)
-
-/turf/Initialize(mapload)
- . = ..()
var/area/A = loc
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
@@ -51,38 +62,40 @@
if(light_power && light_range)
update_light()
- if (opacity)
+ if(opacity)
has_opaque_atom = TRUE
-/hook/startup/proc/smooth_world()
- var/watch = start_watch()
- log_startup_progress("Smoothing atoms...")
- for(var/turf/T in world)
- if(T.smooth)
- queue_smooth(T)
- for(var/A in T)
- var/atom/AA = A
- if(AA.smooth)
- queue_smooth(AA)
- log_startup_progress(" Smoothed atoms in [stop_watch(watch)]s.")
- return 1
+ return INITIALIZE_HINT_NORMAL
-/turf/Destroy()
-// Adds the adjacent turfs to the current atmos processing
- if(SSair)
- for(var/direction in GLOB.cardinal)
- if(atmos_adjacent_turfs & direction)
- var/turf/simulated/T = get_step(src, direction)
- if(istype(T))
- SSair.add_to_active(T)
+/turf/Destroy(force)
+ . = QDEL_HINT_IWILLGC
+ if(!changing_turf)
+ stack_trace("Incorrect turf deletion")
+ changing_turf = FALSE
+ if(force)
+ ..()
+ //this will completely wipe turf state
+ var/turf/B = new world.turf(src)
+ for(var/A in B.contents)
+ qdel(A)
+ return
+ // Adds the adjacent turfs to the current atmos processing
+ for(var/direction in GLOB.cardinal)
+ if(atmos_adjacent_turfs & direction)
+ var/turf/simulated/T = get_step(src, direction)
+ if(istype(T))
+ SSair.add_to_active(T)
+ SSair.remove_from_active(src)
+ visibilityChanged()
+ QDEL_LIST(blueprint_data)
+ initialized = FALSE
..()
- return QDEL_HINT_HARDDEL_NOW
/turf/attack_hand(mob/user as mob)
user.Move_Pulled(src)
/turf/ex_act(severity)
- return 0
+ return FALSE
/turf/rpd_act(mob/user, obj/item/rpd/our_rpd) //This is the default turf behaviour for the RPD; override it as required
if(our_rpd.mode == RPD_ATMOS_MODE)
@@ -100,55 +113,53 @@
else if(our_rpd.mode == RPD_DELETE_MODE)
our_rpd.delete_all_pipes(user, src)
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/beam/pulse))
+/turf/bullet_act(obj/item/projectile/Proj)
+ if(istype(Proj, /obj/item/projectile/beam/pulse))
src.ex_act(2)
..()
- return 0
+ return FALSE
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/bullet/gyro))
+/turf/bullet_act(obj/item/projectile/Proj)
+ if(istype(Proj, /obj/item/projectile/bullet/gyro))
explosion(src, -1, 0, 2)
..()
- return 0
+ return FALSE
-/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
+/turf/Enter(atom/movable/mover as mob|obj, atom/forget)
if(!mover)
- return 1
-
+ return TRUE
// First, make sure it can leave its square
if(isturf(mover.loc))
// Nothing but border objects stop you from leaving a tile, only one loop is needed
for(var/obj/obstacle in mover.loc)
if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget)
- mover.Bump(obstacle, 1)
- return 0
+ mover.Bump(obstacle, TRUE)
+ return FALSE
var/list/large_dense = list()
//Next, check objects to block entry that are on the border
for(var/atom/movable/border_obstacle in src)
- if(border_obstacle.flags&ON_BORDER)
- if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle))
- mover.Bump(border_obstacle, 1)
- return 0
+ if(border_obstacle.flags & ON_BORDER)
+ if(!border_obstacle.CanPass(mover, mover.loc, 1) && (forget != border_obstacle))
+ mover.Bump(border_obstacle, TRUE)
+ return FALSE
else
large_dense += border_obstacle
//Then, check the turf itself
if(!src.CanPass(mover, src))
- mover.Bump(src, 1)
- return 0
+ mover.Bump(src, TRUE)
+ return FALSE
//Finally, check objects/mobs to block entry that are not on the border
for(var/atom/movable/obstacle in large_dense)
- if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle))
- mover.Bump(obstacle, 1)
- return 0
- return 1 //Nothing found to block so return success!
+ if(!obstacle.CanPass(mover, mover.loc, 1) && (forget != obstacle))
+ mover.Bump(obstacle, TRUE)
+ return FALSE
+ return TRUE //Nothing found to block so return success!
-
-/turf/Entered(atom/movable/M, atom/OL, ignoreRest = 0)
+/turf/Entered(atom/movable/M, atom/OL, ignoreRest = FALSE)
..()
if(ismob(M))
var/mob/O = M
@@ -161,7 +172,12 @@
if(loopsanity == 0)
break
loopsanity--
- A.HasProximity(M, 1)
+ A.HasProximity(M)
+
+ // If an opaque movable atom moves around we need to potentially update visibility.
+ if(M.opacity)
+ has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
+ reconsider_lights()
/turf/proc/levelupdate()
for(var/obj/O in src)
@@ -172,7 +188,7 @@
/turf/space/levelupdate()
for(var/obj/O in src)
if(O.level == 1)
- O.hide(0)
+ O.hide(FALSE)
// Removes all signs of lattice on the pos of the turf -Donkieyo
/turf/proc/RemoveLattice()
@@ -180,6 +196,9 @@
if(L)
qdel(L)
+/turf/proc/dismantle_wall(devastated = FALSE, explode = FALSE)
+ return
+
/turf/proc/TerraformTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE)
return ChangeTurf(path, defer_change, keep_icon, ignore_air)
@@ -200,10 +219,10 @@
var/old_corners = corners
BeforeChange()
- if(SSair)
- SSair.remove_from_active(src)
var/old_baseturf = baseturf
+ changing_turf = TRUE
+ qdel(src) //Just get the side effects and call Destroy
var/turf/W = new path(src)
W.baseturf = old_baseturf
@@ -216,7 +235,6 @@
if(SSlighting.initialized)
recalc_atom_opacity()
lighting_object = old_lighting_object
-
affecting_lights = old_affecting_lights
corners = old_corners
if(old_opacity != opacity || dynamic_lighting != old_dynamic_lighting)
@@ -239,7 +257,7 @@
return
// I'm including `ignore_air` because BYOND lacks positional-only arguments
-/turf/proc/AfterChange(ignore_air, keep_cabling = FALSE) //called after a turf has been replaced in ChangeTurf()
+/turf/proc/AfterChange(ignore_air = FALSE, keep_cabling = FALSE) //called after a turf has been replaced in ChangeTurf()
levelupdate()
CalculateAdjacentTurfs()
@@ -250,7 +268,7 @@
for(var/obj/structure/cable/C in contents)
qdel(C)
-/turf/simulated/AfterChange(ignore_air, keep_cabling = FALSE)
+/turf/simulated/AfterChange(ignore_air = FALSE, keep_cabling = FALSE)
..()
RemoveLattice()
if(!ignore_air)
@@ -259,32 +277,38 @@
//////Assimilate Air//////
/turf/simulated/proc/Assimilate_Air()
if(air)
- var/aoxy = 0//Holders to assimilate air from nearby turfs
+ var/aoxy = 0 //Holders to assimilate air from nearby turfs
var/anitro = 0
var/aco = 0
var/atox = 0
+ var/asleep = 0
+ var/ab = 0
var/atemp = 0
var/turf_count = 0
for(var/direction in GLOB.cardinal)//Only use cardinals to cut down on lag
- var/turf/T = get_step(src,direction)
- if(istype(T,/turf/space))//Counted as no air
+ var/turf/T = get_step(src, direction)
+ if(istype(T, /turf/space))//Counted as no air
turf_count++//Considered a valid turf for air calcs
continue
- else if(istype(T,/turf/simulated/floor))
+ else if(istype(T, /turf/simulated/floor))
var/turf/simulated/S = T
if(S.air)//Add the air's contents to the holders
aoxy += S.air.oxygen
anitro += S.air.nitrogen
aco += S.air.carbon_dioxide
atox += S.air.toxins
+ asleep += S.air.sleeping_agent
+ ab += S.air.agent_b
atemp += S.air.temperature
turf_count++
- air.oxygen = (aoxy/max(turf_count,1))//Averages contents of the turfs, ignoring walls and the like
- air.nitrogen = (anitro/max(turf_count,1))
- air.carbon_dioxide = (aco/max(turf_count,1))
- air.toxins = (atox/max(turf_count,1))
- air.temperature = (atemp/max(turf_count,1))//Trace gases can get bant
+ air.oxygen = (aoxy / max(turf_count, 1)) //Averages contents of the turfs, ignoring walls and the like
+ air.nitrogen = (anitro / max(turf_count, 1))
+ air.carbon_dioxide = (aco / max(turf_count, 1))
+ air.toxins = (atox / max(turf_count, 1))
+ air.sleeping_agent = (asleep / max(turf_count, 1))
+ air.agent_b = (ab / max(turf_count, 1))
+ air.temperature = (atemp / max(turf_count, 1))
if(SSair)
SSair.add_to_active(src)
@@ -292,15 +316,17 @@
ChangeTurf(baseturf)
new /obj/structure/lattice(locate(x, y, z))
+/turf/proc/remove_plating(mob/user)
+ return
+
/turf/proc/kill_creatures(mob/U = null)//Will kill people/creatures and damage mechs./N
//Useful to batch-add creatures to the list.
for(var/mob/living/M in src)
- if(M==U) continue//Will not harm U. Since null != M, can be excluded to kill everyone.
- spawn(0)
- M.gib()
+ if(M == U)
+ continue//Will not harm U. Since null != M, can be excluded to kill everyone.
+ INVOKE_ASYNC(M, /mob/.proc/gib)
for(var/obj/mecha/M in src)//Mecha are not gibbed but are damaged.
- spawn(0)
- M.take_damage(100, "brute")
+ INVOKE_ASYNC(M, /obj/mecha/.proc/take_damage, 100, "brute")
/turf/proc/Bless()
flags |= NOJAUNT
@@ -309,6 +335,10 @@
for(var/atom/movable/AM in contents)
AM.get_spooked()
+// Defined here to avoid runtimes
+/turf/proc/MakeDry(wet_setting = TURF_WET_WATER)
+ return
+
/turf/proc/burn_down()
return
@@ -353,11 +383,11 @@
// Returns the surrounding simulated turfs with open links
// Including through doors openable with the ID
-/turf/proc/AdjacentTurfsWithAccess(var/obj/item/card/id/ID = null,var/list/closed)//check access if one is passed
+/turf/proc/AdjacentTurfsWithAccess(obj/item/card/id/ID = null, list/closed)//check access if one is passed
var/list/L = new()
var/turf/simulated/T
- for(var/dir in list(NORTHWEST,NORTHEAST,SOUTHEAST,SOUTHWEST,NORTH,EAST,SOUTH,WEST)) //arbitrarily ordered list to favor non-diagonal moves in case of ties
- T = get_step(src,dir)
+ for(var/dir in GLOB.alldirs2) //arbitrarily ordered list to favor non-diagonal moves in case of ties
+ T = get_step(src, dir)
if(T in closed) //turf already proceeded in A*
continue
if(istype(T) && !T.density)
@@ -366,11 +396,11 @@
return L
//Idem, but don't check for ID and goes through open doors
-/turf/proc/AdjacentTurfs(var/list/closed)
+/turf/proc/AdjacentTurfs(list/closed)
var/list/L = new()
var/turf/simulated/T
- for(var/dir in list(NORTHWEST,NORTHEAST,SOUTHEAST,SOUTHWEST,NORTH,EAST,SOUTH,WEST)) //arbitrarily ordered list to favor non-diagonal moves in case of ties
- T = get_step(src,dir)
+ for(var/dir in GLOB.alldirs2) //arbitrarily ordered list to favor non-diagonal moves in case of ties
+ T = get_step(src, dir)
if(T in closed) //turf already proceeded by A*
continue
if(istype(T) && !T.density)
@@ -379,11 +409,11 @@
return L
// check for all turfs, including unsimulated ones
-/turf/proc/AdjacentTurfsSpace(var/obj/item/card/id/ID = null, var/list/closed)//check access if one is passed
+/turf/proc/AdjacentTurfsSpace(obj/item/card/id/ID = null, list/closed)//check access if one is passed
var/list/L = new()
var/turf/T
- for(var/dir in list(NORTHWEST,NORTHEAST,SOUTHEAST,SOUTHWEST,NORTH,EAST,SOUTH,WEST)) //arbitrarily ordered list to favor non-diagonal moves in case of ties
- T = get_step(src,dir)
+ for(var/dir in GLOB.alldirs2) //arbitrarily ordered list to favor non-diagonal moves in case of ties
+ T = get_step(src, dir)
if(T in closed) //turf already proceeded by A*
continue
if(istype(T) && !T.density)
@@ -400,20 +430,21 @@
//////////////////////////////
//Distance associates with all directions movement
-/turf/proc/Distance(var/turf/T)
- return get_dist(src,T)
+/turf/proc/Distance(turf/T)
+ return get_dist(src, T)
// This Distance proc assumes that only cardinal movement is
// possible. It results in more efficient (CPU-wise) pathing
// for bots and anything else that only moves in cardinal dirs.
/turf/proc/Distance_cardinal(turf/T)
- if(!src || !T) return 0
+ if(!src || !T)
+ return 0
return abs(src.x - T.x) + abs(src.y - T.y)
////////////////////////////////////////////////////
/turf/acid_act(acidpwr, acid_volume)
- . = 1
+ . = TRUE
var/acid_type = /obj/effect/acid
if(acidpwr >= 200) //alien acid power
acid_type = /obj/effect/acid/alien
@@ -438,7 +469,7 @@
if(!forced)
return
if(has_gravity(src))
- playsound(src, "bodyfall", 50, 1)
+ playsound(src, "bodyfall", 50, TRUE)
/turf/singularity_act()
if(intact)
@@ -448,7 +479,7 @@
if(O.invisibility == INVISIBILITY_MAXIMUM)
O.singularity_act()
ChangeTurf(baseturf)
- return(2)
+ return 2
/turf/proc/visibilityChanged()
if(SSticker)
@@ -459,25 +490,25 @@
if(istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
for(var/obj/structure/cable/LC in src)
- if(LC.d1 == 0 || LC.d2==0)
- LC.attackby(C,user)
+ if(LC.d1 == 0 || LC.d2 == 0)
+ LC.attackby(C, user)
return
C.place_turf(src, user)
- return 1
+ return TRUE
else if(istype(I, /obj/item/twohanded/rcl))
var/obj/item/twohanded/rcl/R = I
if(R.loaded)
for(var/obj/structure/cable/LC in src)
- if(LC.d1 == 0 || LC.d2==0)
+ if(LC.d1 == 0 || LC.d2 == 0)
LC.attackby(R, user)
return
R.loaded.place_turf(src, user)
R.is_empty(user)
- return 0
+ return FALSE
/turf/proc/can_have_cabling()
- return 1
+ return TRUE
/turf/proc/can_lay_cable()
return can_have_cabling() & !intact
@@ -502,18 +533,15 @@
I.appearance = AM.appearance
I.appearance_flags = RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM
I.loc = src
- I.dir = AM.dir
+ I.setDir(AM.dir)
I.alpha = 128
-
- if(!blueprint_data)
- blueprint_data = list()
- blueprint_data += I
+ LAZYADD(blueprint_data, I)
/turf/proc/add_blueprints_preround(atom/movable/AM)
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
add_blueprints(AM)
-/turf/proc/empty(turf_type=/turf/space)
+/turf/proc/empty(turf_type = /turf/space)
// Remove all atoms except observers, landmarks, docking ports, and (un)`simulated` atoms (lighting overlays)
var/turf/T0 = src
for(var/X in T0.GetAllContents())
@@ -526,13 +554,13 @@
continue
if(istype(A, /obj/docking_port))
continue
- qdel(A, force=TRUE)
+ qdel(A, force = TRUE)
T0.ChangeTurf(turf_type)
SSair.remove_from_active(T0)
T0.CalculateAdjacentTurfs()
- SSair.add_to_active(T0,1)
+ SSair.add_to_active(T0, TRUE)
/turf/AllowDrop()
return TRUE
diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm
index 688dc778ce3..02af9173e2b 100644
--- a/code/game/turfs/unsimulated.dm
+++ b/code/game/turfs/unsimulated.dm
@@ -40,6 +40,6 @@
nitrogen = 0
temperature = TCMB
-/turf/unsimulated/floor/plating/airless/New()
- ..()
+/turf/unsimulated/floor/plating/airless/Initialize(mapload)
+ . = ..()
name = "plating"
diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm
index f6a3a62c324..a7c73971e99 100644
--- a/code/game/turfs/unsimulated/beach.dm
+++ b/code/game/turfs/unsimulated/beach.dm
@@ -3,9 +3,9 @@
icon = 'icons/misc/beach.dmi'
var/water_overlay_image = null
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/turf/unsimulated/beach/New()
- ..()
+
+/turf/unsimulated/beach/Initialize(mapload)
+ . = ..()
if(water_overlay_image)
var/image/overlay_image = image('icons/misc/beach.dmi', icon_state = water_overlay_image, layer = ABOVE_MOB_LAYER)
overlay_image.plane = GAME_PLANE
@@ -15,10 +15,10 @@
name = "Sand"
icon_state = "desert"
mouse_opacity = MOUSE_OPACITY_ICON
-
-/turf/unsimulated/beach/sand/New() //adds some aesthetic randomness to the beach sand
+
+/turf/unsimulated/beach/sand/Initialize(mapload)
+ . = ..() //adds some aesthetic randomness to the beach sand
icon_state = pick("desert", "desert0", "desert1", "desert2", "desert3", "desert4")
- ..()
/turf/unsimulated/beach/sand/dense //for boundary "walls"
density = 1
@@ -42,7 +42,7 @@
/turf/unsimulated/beach/water/Entered(atom/movable/AM, atom/OldLoc)
. = ..()
if(!linkedcontroller)
- return
+ return
if(ismob(AM))
linkedcontroller.mobinpool += AM
@@ -79,8 +79,8 @@
/turf/unsimulated/beach/water/edge_drop)
var/obj/effect/beach_drop_overlay/water_overlay
-/turf/unsimulated/beach/water/drop/New()
- ..()
+/turf/unsimulated/beach/water/drop/Initialize(mapload)
+ . = ..()
water_overlay = new(src)
/turf/unsimulated/beach/water/drop/Destroy()
diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm
index 28f4e359223..750ebe015ae 100644
--- a/code/game/turfs/unsimulated/floor.dm
+++ b/code/game/turfs/unsimulated/floor.dm
@@ -7,8 +7,8 @@
name = "grass patch"
icon_state = "grass1"
-/turf/unsimulated/floor/grass/New()
- ..()
+/turf/unsimulated/floor/grass/Initialize(mapload)
+ . = ..()
icon_state = "grass[rand(1,4)]"
/turf/unsimulated/floor/snow
@@ -20,8 +20,8 @@
name = "alien floor"
icon_state = "alienpod1"
-/turf/unsimulated/floor/abductor/New()
- ..()
+/turf/unsimulated/floor/abductor/Initialize(mapload)
+ . = ..()
icon_state = "alienpod[rand(1,9)]"
/turf/unsimulated/floor/vox
diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm
index 2683e236269..95b11353b86 100644
--- a/code/game/verbs/who.dm
+++ b/code/game/verbs/who.dm
@@ -27,7 +27,7 @@
entry += " - Observing"
else
entry += " - DEAD"
- else if(istype(C.mob, /mob/new_player))
+ else if(isnewplayer(C.mob))
entry += " - New Player"
else
entry += " - DEAD"
@@ -90,7 +90,7 @@
if(isobserver(C.mob))
msg += " - Observing"
- else if(istype(C.mob,/mob/new_player))
+ else if(isnewplayer(C.mob))
msg += " - Lobby"
else
msg += " - Playing"
@@ -106,7 +106,7 @@
if(isobserver(C.mob))
modmsg += " - Observing"
- else if(istype(C.mob,/mob/new_player))
+ else if(isnewplayer(C.mob))
modmsg += " - Lobby"
else
modmsg += " - Playing"
diff --git a/code/game/world.dm b/code/game/world.dm
index 762a0be70a8..fdb0b8f63be 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -1,14 +1,23 @@
-#define RECOMMENDED_VERSION 510
-
GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG)
/world/New()
+ //temporary file used to record errors with loading config, moved to log directory once logging is set up
+ GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = "data/logs/config_error.log"
+ load_configuration()
+ // Setup all log paths and stamp them with startups
SetupLogs()
enable_debugger() // Enable the extools debugger
log_world("World loaded at [time_stamp()]")
log_world("[GLOB.vars.len - GLOB.gvars_datum_in_built_vars.len] global variables")
+ connectDB() // This NEEDS TO HAPPEN EARLY. I CANNOT STRESS THIS ENOUGH!!!!!!! -aa
+ load_admins() // Same here
- if(byond_version < RECOMMENDED_VERSION)
+ #ifdef UNIT_TESTS
+ log_world("Unit Tests Are Enabled!")
+ #endif
+
+
+ if(byond_version < MIN_COMPILER_VERSION || byond_build < MIN_COMPILER_BUILD)
log_world("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND")
if(config && config.server_name != null && config.server_suffix && world.port > 0)
@@ -17,8 +26,7 @@ GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG)
GLOB.timezoneOffset = text2num(time2text(0, "hh")) * 36000
- makeDatumRefLists()
- callHook("startup")
+ startup_procs() // Call procs that need to occur on startup (Generate lists, load MOTD, etc)
src.update_status()
@@ -26,16 +34,24 @@ GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG)
. = ..()
- // Create robolimbs for chargen.
- populate_robolimb_list()
-
Master.Initialize(10, FALSE)
-
-#undef RECOMMENDED_VERSION
+ #ifdef UNIT_TESTS
+ HandleTestRun()
+ #endif
return
+// This is basically a replacement for hook/startup. Please dont shove random bullshit here
+// If it doesnt need to happen IMMEDIATELY on world load, make a subsystem for it
+/world/proc/startup_procs()
+ LoadBans() // Load up who is banned and who isnt. DONT PUT THIS IN A SUBSYSTEM IT WILL TAKE TOO LONG TO BE CALLED
+ jobban_loadbanfile() // Load up jobbans. Again, DO NOT PUT THIS IN A SUBSYSTEM IT WILL TAKE TOO LONG TO BE CALLED
+ load_motd() // Loads up the MOTD (Welcome message players see when joining the server)
+ load_mode() // Loads up the gamemode
+ investigate_reset() // This is part of the admin investigate system. PLEASE DONT SS THIS EITHER
+ makeDatumRefLists() // Setups up lists of datums and their subtypes
+
//world/Topic(href, href_list[])
// to_chat(world, "Received a Topic() call!")
// to_chat(world, "[href]")
@@ -226,7 +242,7 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
if(!C)
return "No client with that name on server"
- del(C)
+ qdel(C)
return "Kick Successful"
@@ -242,7 +258,7 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
if(!key_valid)
return keySpamProtect(addr)
if(input["req"] == "public")
- hub_password = hub_password_base
+ hub_password = initial(hub_password)
update_status()
return "Set listed status to public."
else
@@ -263,6 +279,10 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time)
if(reason == 1) //special reboot, do none of the normal stuff
if(usr)
+ if(!check_rights(R_SERVER))
+ message_admins("[key_name_admin(usr)] attempted to restart the server via the Profiler, without access.")
+ log_admin("[key_name(usr)] attempted to restart the server via the Profiler, without access.")
+ return
message_admins("[key_name_admin(usr)] has requested an immediate world restart via client side debugging tools")
log_admin("[key_name(usr)] has requested an immediate world restart via client side debugging tools")
spawn(0)
@@ -307,6 +327,11 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
GLOB.dbcon.Disconnect() // DCs cleanly from the database
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
+ #ifdef UNIT_TESTS
+ FinishTestRun()
+ return
+ #endif
+
for(var/client/C in GLOB.clients)
if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
@@ -320,11 +345,6 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
else
..(0)
-
-/hook/startup/proc/loadMode()
- world.load_mode()
- return 1
-
/world/proc/load_mode()
var/list/Lines = file2list("data/mode.txt")
if(Lines.len)
@@ -337,10 +357,6 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
fdel(F)
F << the_mode
-/hook/startup/proc/loadMOTD()
- world.load_motd()
- return 1
-
/world/proc/load_motd()
GLOB.join_motd = file2text("config/motd.txt")
GLOB.join_tos = file2text("config/tos.txt")
@@ -410,10 +426,12 @@ GLOBAL_VAR_INIT(failed_old_db_connections, 0)
GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
+ GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
start_log(GLOB.world_game_log)
start_log(GLOB.world_href_log)
start_log(GLOB.world_runtime_log)
start_log(GLOB.world_qdel_log)
+ start_log(GLOB.tgui_log)
// This log follows a special format and this path should NOT be used for anything else
GLOB.runtime_summary_log = "data/logs/runtime_summary.log"
@@ -427,7 +445,7 @@ GLOBAL_VAR_INIT(failed_old_db_connections, 0)
fdel(GLOB.config_error_log)
-/hook/startup/proc/connectDB()
+/world/proc/connectDB()
if(!setup_database_connection())
log_world("Your server failed to establish a connection with the feedback database.")
else
diff --git a/code/hub.dm b/code/hub.dm
index 665193a9d5b..32fe613399e 100644
--- a/code/hub.dm
+++ b/code/hub.dm
@@ -3,7 +3,6 @@
hub = "Exadv1.spacestation13"
hub_password = "kMZy3U5jJHSiBQjr"
name = "Space Station 13"
- /var/hub_password_base = "kMZy3U5jJHSiBQjr"
/* This is for any host that would like their server to appear on the main SS13 hub.
To use it, simply replace the password above, with the password found below, and it should work.
If not, let us know on the main tgstation IRC channel of irc.rizon.net #tgstation13 we can help you there.
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index 21b59586bfd..09df94dc06e 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -146,7 +146,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
if(kickbannedckey)
if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
- del(banned_mob.client)
+ qdel(banned_mob.client)
if(isjobban)
jobban_client_fullban(ckey, job)
@@ -211,7 +211,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
query.Execute()
while(query.NextRow())
ban_id = query.item[1]
- ban_number++;
+ ban_number++
if(ban_number == 0)
to_chat(usr, "Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.")
@@ -314,7 +314,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
query.Execute()
while(query.NextRow())
pckey = query.item[1]
- ban_number++;
+ ban_number++
if(ban_number == 0)
to_chat(usr, "Database update failed due to a ban id not being present in the database.")
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index c7f2baac4ef..d9ceba62830 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -36,17 +36,6 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
// message_admins("Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
- //check if the IP address is a known Tor node
- if(config.ToRban && ToRban_isbanned(address))
- log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned: Tor")
- message_admins("Failed Login: [key] - Banned: Tor")
- //ban their computer_id and ckey for posterity
- AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0)
- var/mistakemessage = ""
- if(config.banappeals)
- mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
- return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
-
//check if the IP address is a known proxy/vpn, and the user is not whitelisted
if(check_ipintel && config.ipintel_email && config.ipintel_whitelist && ipintel_is_banned(key, address))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Proxy/VPN")
diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm
index 7b9a9330704..293504919d4 100644
--- a/code/modules/admin/NewBan.dm
+++ b/code/modules/admin/NewBan.dm
@@ -58,9 +58,6 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
GLOB.CMinutes = (world.realtime / 10) / 60
return 1
-/hook/startup/proc/loadBans()
- return LoadBans()
-
/proc/LoadBans()
GLOB.banlist_savefile = new("data/banlist.bdb")
@@ -106,7 +103,8 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
GLOB.banlist_savefile.cd = "/base"
if( GLOB.banlist_savefile.dir.Find("[ckey][computerid]") )
- to_chat(usr, "Ban already exists.")
+ if(usr)
+ to_chat(usr, "Ban already exists.")
return 0
else
GLOB.banlist_savefile.dir.Add("[ckey][computerid]")
diff --git a/code/modules/admin/ToRban.dm b/code/modules/admin/ToRban.dm
deleted file mode 100644
index b486f168503..00000000000
--- a/code/modules/admin/ToRban.dm
+++ /dev/null
@@ -1,89 +0,0 @@
-//By Carnwennan
-//fetches an external list and processes it into a list of ip addresses.
-//It then stores the processed list into a savefile for later use
-#define TORFILE "data/ToR_ban.bdb"
-#define TOR_UPDATE_INTERVAL 216000 //~6 hours
-
-/proc/ToRban_isbanned(var/ip_address)
- var/savefile/F = new(TORFILE)
- if(F)
- if( ip_address in F.dir )
- return 1
- return 0
-
-/proc/ToRban_autoupdate()
- var/savefile/F = new(TORFILE)
- if(F)
- var/last_update
- F["last_update"] >> last_update
- if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while
- ToRban_update()
- return
-
-/proc/ToRban_update()
- spawn(0)
- log_world("Downloading updated ToR data...")
- var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
-
- var/list/rawlist = file2list(http["CONTENT"])
- if(rawlist.len)
- fdel(TORFILE)
- var/savefile/F = new(TORFILE)
- for( var/line in rawlist )
- if(!line) continue
- if( copytext(line,1,12) == "ExitAddress" )
- var/cleaned = copytext(line,13,length(line)-19)
- if(!cleaned) continue
- F[cleaned] << 1
- to_chat(F["last_update"], world.realtime)
- log_world("ToR data updated!")
- if(usr)
- to_chat(usr, "ToRban updated.")
- return 1
- log_world("ToR data update aborted: no data.")
- return 0
-
-/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find"))
- set name = "ToRban"
- set category = "Server"
- if(!holder) return
- switch(task)
- if("update")
- ToRban_update()
- if("toggle")
- if(config)
- if(config.ToRban)
- config.ToRban = 0
- message_admins("ToR banning disabled.")
- else
- config.ToRban = 1
- message_admins("ToR banning enabled.")
- if("show")
- var/savefile/F = new(TORFILE)
- var/dat
- if( length(F.dir) )
- for( var/i=1, i<=length(F.dir), i++ )
- dat += "
#[i]
[F.dir[i]]
"
- dat = "
[dat]
"
- else
- dat = "No addresses in list."
- src << browse(dat,"window=ToRban_show")
- if("remove")
- var/savefile/F = new(TORFILE)
- var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir
- if(choice)
- F.dir.Remove(choice)
- to_chat(src, "Address removed")
- if("remove all")
- to_chat(src, "[TORFILE] was [fdel(TORFILE)?"":"not "]removed.")
- if("find")
- var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text
- if(input)
- if(ToRban_isbanned(input))
- to_chat(src, "Address is a known ToR address")
- else
- to_chat(src, "Address is not a known ToR address")
- return
-
-#undef TORFILE
-#undef TOR_UPDATE_INTERVAL
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 8cb1c831c17..958dedae362 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -72,7 +72,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
body += "\[" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]\]"
- if(istype(M, /mob/new_player))
+ if(isnewplayer(M))
body += " Hasn't Entered Game "
else
body += " \[Heal\] "
@@ -148,7 +148,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += {" | Cryo "}
if(M.client)
- if(!istype(M, /mob/new_player))
+ if(!isnewplayer(M))
body += "
"
body += "Transformation:"
body += " "
@@ -1005,13 +1005,13 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
/proc/kick_clients_in_lobby(message, kick_only_afk = 0)
var/list/kicked_client_names = list()
for(var/client/C in GLOB.clients)
- if(istype(C.mob, /mob/new_player))
+ if(isnewplayer(C.mob))
if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk
continue
if(message)
to_chat(C, message)
kicked_client_names.Add("[C.ckey]")
- del(C)
+ qdel(C)
return kicked_client_names
//returns 1 to let the dragdrop code know we are trapping this event
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 13b786c5174..a627c96148f 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -11,10 +11,6 @@
/proc/investigate_subject2file(var/subject)
return file("[INVESTIGATE_DIR][subject].html")
-/hook/startup/proc/resetInvestigate()
- investigate_reset()
- return 1
-
/proc/investigate_reset()
if(fdel(INVESTIGATE_DIR)) return 1
return 0
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index f8a31f885ed..342ba454526 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -44,22 +44,24 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if("mod") rights |= R_MOD
if("mentor") rights |= R_MENTOR
if("proccall") rights |= R_PROCCALL
+ if("viewruntimes") rights |= R_VIEWRUNTIMES
GLOB.admin_ranks[rank] = rights
previous_rights = rights
#ifdef TESTING
var/msg = "Permission Sets Built:\n"
- for(var/rank in admin_ranks)
+ for(var/rank in GLOB.admin_ranks)
msg += "\t[rank] - [GLOB.admin_ranks[rank]]\n"
testing(msg)
#endif
-/hook/startup/proc/loadAdmins()
- load_admins()
- return 1
-
/proc/load_admins()
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Admin reload blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to reload admins via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to reload admins via advanced proc-call")
+ return
//clear the datums references
GLOB.admin_datums.Cut()
for(var/client/C in GLOB.admins)
@@ -67,6 +69,10 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
C.holder = null
GLOB.admins.Cut()
+ // Remove all profiler access
+ for(var/A in world.GetConfig("admin"))
+ world.SetConfig("APP/admin", A, null)
+
if(config.admin_legacy_system)
load_admin_ranks()
@@ -97,6 +103,9 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
//create the admin datum and store it for later use
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
+ if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
+ world.SetConfig("APP/admin", ckey, "role=admin")
+
//find the client for a ckey if they are connected and associate them with the new admin datum
D.associate(GLOB.directory[ckey])
@@ -121,6 +130,9 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if(istext(rights)) rights = text2num(rights)
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
+ if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
+ world.SetConfig("APP/admin", ckey, "role=admin")
+
//find the client for a ckey if they are connected and associate them with the new admin datum
D.associate(GLOB.directory[ckey])
if(!GLOB.admin_datums)
@@ -141,12 +153,12 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
#ifdef TESTING
-/client/verb/changerank(newrank in admin_ranks)
+/client/verb/changerank(newrank in GLOB.admin_ranks)
if(holder)
holder.rank = newrank
- holder.rights = admin_ranks[newrank]
+ holder.rights = GLOB.admin_ranks[newrank]
else
- holder = new /datum/admins(newrank,admin_ranks[newrank],ckey)
+ holder = new /datum/admins(newrank,GLOB.admin_ranks[newrank],ckey)
remove_admin_verbs()
holder.associate(src)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 34929b52f53..f310a4502fa 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -68,7 +68,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/aooc,
/client/proc/freeze,
- /client/proc/freezemecha,
/client/proc/alt_check,
/client/proc/secrets,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
@@ -126,7 +125,6 @@ GLOBAL_LIST_INIT(admin_verbs_spawn, list(
/client/proc/admin_deserialize
))
GLOBAL_LIST_INIT(admin_verbs_server, list(
- /client/proc/ToRban,
/client/proc/Set_Holiday,
/datum/admins/proc/startnow,
/datum/admins/proc/restart,
@@ -230,7 +228,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
/client/proc/add_admin_verbs()
if(holder)
- verbs += GLOB.admin_verbs_default
+ // If they have ANYTHING OTHER THAN ONLY VIEW RUNTIMES (65536), then give them the default admin verbs
+ if(holder.rights != R_VIEWRUNTIMES)
+ verbs += GLOB.admin_verbs_default
if(holder.rights & R_BUILDMODE)
verbs += /client/proc/togglebuildmodeself
if(holder.rights & R_ADMIN)
@@ -246,6 +246,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
verbs += GLOB.admin_verbs_server
if(holder.rights & R_DEBUG)
verbs += GLOB.admin_verbs_debug
+ spawn(1)
+ control_freak = 0 // Setting control_freak to 0 allows you to use the Profiler and other client-side tools
if(holder.rights & R_POSSESS)
verbs += GLOB.admin_verbs_possess
if(holder.rights & R_PERMISSIONS)
@@ -264,6 +266,11 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
verbs += GLOB.admin_verbs_mentor
if(holder.rights & R_PROCCALL)
verbs += GLOB.admin_verbs_proccall
+ if(holder.rights & R_VIEWRUNTIMES)
+ verbs += /client/proc/view_runtimes
+ spawn(1) // This setting exposes the profiler for people with R_VIEWRUNTIMES. They must still have it set in cfg/admin.txt
+ control_freak = 0
+
/client/proc/remove_admin_verbs()
verbs.Remove(
@@ -329,7 +336,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
ghost.reenter_corpse()
log_admin("[key_name(usr)] re-entered their body")
feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- else if(istype(mob,/mob/new_player))
+ else if(isnewplayer(mob))
to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or observe first.")
else
//ghostize
@@ -534,7 +541,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [key_name(C)] resulting in a [AUTOBANTIME] minute ban")
to_chat(C, "You have been autobanned due to a warning by [ckey]. This is a temporary ban, it will be removed in [AUTOBANTIME] minutes.")
- del(C)
+ qdel(C)
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
@@ -818,7 +825,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
return
if(holder)
- admin_log_and_message_admins("is altering the appearance of [H].")
+ log_and_message_admins("is altering the appearance of [H].")
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0)
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -849,10 +856,10 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
if("Yes")
- admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
+ log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
if("No")
- admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
+ log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm
index 9efc4c9ce88..2122f88f4ed 100644
--- a/code/modules/admin/banjob.dm
+++ b/code/modules/admin/banjob.dm
@@ -56,10 +56,6 @@ DEBUG
jobban_loadbanfile()
*/
-/hook/startup/proc/loadJobBans()
- jobban_loadbanfile()
- return 1
-
/proc/jobban_loadbanfile()
if(config.ban_legacy_system)
var/savefile/S=new("data/job_full.ban")
diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 740d182f3f2..470293bfe76 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -16,6 +16,11 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
var/admincaster_signature //What you'll sign the newsfeeds as
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Admin rank creation blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to create a new admin rank via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to edit feedback a new admin rank via advanced proc-call")
+ return
if(!ckey)
error("Admin datum created without a ckey argument. Datum has been deleted")
qdel(src)
@@ -26,10 +31,20 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
GLOB.admin_datums[ckey] = src
/datum/admins/Destroy()
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Admin rank deletion blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to delete an admin rank via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to delete an admin rank via advanced proc-call")
+ return
..()
return QDEL_HINT_HARDDEL_NOW
/datum/admins/proc/associate(client/C)
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Rank association blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to associate an admin rank to a new client via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to associate an admin rank to a new client via advanced proc-call")
+ return
if(istype(C))
owner = C
owner.holder = src
@@ -39,6 +54,11 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
GLOB.admins |= C
/datum/admins/proc/disassociate()
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Rank disassociation blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to disassociate an admin rank from a client via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to disassociate an admin rank from a client via advanced proc-call")
+ return
if(owner)
GLOB.admins -= owner
owner.remove_admin_verbs()
@@ -88,6 +108,11 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
return 0
/client/proc/deadmin()
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Deadmin blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to de-admin a client via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to de-admin a client via advanced proc-call")
+ return
GLOB.admin_datums -= ckey
if(holder)
holder.disassociate()
diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm
index 795538c7c33..952630c798a 100644
--- a/code/modules/admin/permissionverbs/permissionedit.dm
+++ b/code/modules/admin/permissionverbs/permissionedit.dm
@@ -102,6 +102,11 @@
to_chat(usr, "Admin rank changed.")
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
+ if(IsAdminAdvancedProcCall())
+ to_chat(usr, "Admin edit blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
+ log_admin("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
+ return
if(config.admin_legacy_system)
return
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index c4313354ff1..1c6bab4d3cd 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -2,6 +2,10 @@
/datum/admins/proc/player_panel_new()//The new one
if(!usr.client.holder)
return
+ // This stops the panel from being invoked by mentors who press F7.
+ if(!check_rights(R_ADMIN))
+ message_admins("[key_name_admin(usr)] attempted to invoke player panel without admin rights. If this is a mentor, its a chance they accidentally hit F7. If this is NOT a mentor, there is a high chance an exploit is being used")
+ return
var/dat = "Admin Player Panel"
//javascript, the part that does most of the work~
@@ -264,7 +268,7 @@
else
M_job = "Living"
- else if(istype(M,/mob/new_player))
+ else if(isnewplayer(M))
M_job = "New player"
else if(isobserver(M))
@@ -352,7 +356,7 @@
dat += "
[M.real_name]
"
else if(istype(M, /mob/living/silicon/pai))
dat += "
"
dat += "Current Game Mode: [SSticker.mode.name] "
@@ -485,6 +491,9 @@
if(SSticker.mode.wizards.len)
dat += check_role_table("Wizards", SSticker.mode.wizards)
+ if(SSticker.mode.apprentices.len)
+ dat += check_role_table("Apprentices", SSticker.mode.apprentices)
+
if(SSticker.mode.raiders.len)
dat += check_role_table("Raiders", SSticker.mode.raiders)
@@ -492,7 +501,7 @@
dat += check_role_table("Ninjas", ticker.mode.ninjas)*/
if(SSticker.mode.cult.len)
- dat += check_role_table("Cultists", SSticker.mode.cult, 0)
+ dat += check_role_table("Cultists", SSticker.mode.cult)
dat += " use Cult Mindspeak"
if(GAMEMODE_IS_CULT)
var/datum/game_mode/cult/cult_round = SSticker.mode
@@ -562,6 +571,15 @@
if(SSticker.mode.ert.len)
dat += check_role_table("ERT", SSticker.mode.ert)
+ //list active security force count, so admins know how bad things are
+ var/list/sec_list = check_active_security_force()
+ dat += "
Security
"
+ dat += "
Total:
[sec_list[1]]
"
+ dat += "
Active:
[sec_list[2]]
"
+ dat += "
Dead:
[sec_list[3]]
"
+ dat += "
Antag:
[sec_list[4]]
"
+ dat += "
"
+
dat += ""
usr << browse(dat, "window=roundstatus;size=400x500")
else
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index e4c889ec309..cbda6699694 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -105,7 +105,7 @@
Turn all humans into monkeys Make all items look like guns Warp all Players to Prison
- Make all players retarded
+ Make all players stupid Misc Remove firesuits, grilles, and podsTriple AI mode (needs to be used in the lobby)
diff --git a/code/modules/admin/sql_notes.dm b/code/modules/admin/sql_notes.dm
index 238c380f417..04e28737479 100644
--- a/code/modules/admin/sql_notes.dm
+++ b/code/modules/admin/sql_notes.dm
@@ -2,7 +2,8 @@
if(checkrights && !check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
- to_chat(usr, "Failed to establish database connection.")
+ if(usr)
+ to_chat(usr, "Failed to establish database connection.")
return
if(!target_ckey)
@@ -19,7 +20,8 @@
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
return
if(!query_find_ckey.NextRow())
- to_chat(usr, "[target_ckey] has not been seen before, you can only add notes to known players.")
+ if(usr)
+ to_chat(usr, "[target_ckey] has not been seen before, you can only add notes to known players.")
return
var/exp_data = query_find_ckey.item[2]
@@ -52,8 +54,8 @@
log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n")
return
if(logged)
- log_admin("[key_name(usr)] has added a note to [target_ckey]: [notetext]")
- message_admins("[key_name_admin(usr)] has added a note to [target_ckey]: [notetext]")
+ log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
+ message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
show_note(target_ckey)
/proc/remove_note(note_id)
@@ -63,7 +65,8 @@
var/notetext
var/adminckey
if(!GLOB.dbcon.IsConnected())
- to_chat(usr, "Failed to establish database connection.")
+ if(usr)
+ to_chat(usr, "Failed to establish database connection.")
return
if(!note_id)
return
@@ -82,15 +85,16 @@
var/err = query_del_note.ErrorMsg()
log_game("SQL ERROR removing note from table. Error : \[[err]\]\n")
return
- log_admin("[key_name(usr)] has removed a note made by [adminckey] from [ckey]: [notetext]")
- message_admins("[key_name_admin(usr)] has removed a note made by [adminckey] from [ckey]: [notetext]")
+ log_admin("[usr ? key_name(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]: [notetext]")
+ message_admins("[usr ? key_name_admin(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]: [notetext]")
show_note(ckey)
/proc/edit_note(note_id)
if(!check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
- to_chat(usr, "Failed to establish database connection.")
+ if(usr)
+ to_chat(usr, "Failed to establish database connection.")
return
if(!note_id)
return
@@ -117,8 +121,8 @@
var/err = query_update_note.ErrorMsg()
log_game("SQL ERROR editing note. Error : \[[err]\]\n")
return
- log_admin("[key_name(usr)] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
- message_admins("[key_name_admin(usr)] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
+ log_admin("[usr ? key_name(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
+ message_admins("[usr ? key_name_admin(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
show_note(target_ckey)
/proc/show_note(target_ckey, index, linkless = 0)
@@ -186,9 +190,13 @@
var/err = query_list_notes.ErrorMsg()
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
return
+ to_chat(usr, "Started regex note search for [search]. Please wait for results...")
+ message_admins("[usr.ckey] has started a note search with the following regex: [search] | CPU usage may be higher.")
while(query_list_notes.NextRow())
index_ckey = query_list_notes.item[1]
output += "[index_ckey] "
+ CHECK_TICK
+ message_admins("The note search started by [usr.ckey] has complete. CPU should return to normal.")
else
output += "
"
- for(var/mob/living/carbon/human/H in GLOB.mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
if(H.ckey)
if(H.dna && H.dna.uni_identity)
dat += "
[H]
[md5(H.dna.uni_identity)]
"
@@ -3482,9 +3486,9 @@
hunter_mind.objectives += protect_objective
SSticker.mode.traitors |= hunter_mob.mind
to_chat(hunter_mob, "ATTENTION: You are now on a mission!")
- to_chat(hunter_mob, "Goal: [killthem ? "MURDER" : "PROTECT"] [H.real_name], currently in [get_area(H.loc)]. ");
+ to_chat(hunter_mob, "Goal: [killthem ? "MURDER" : "PROTECT"] [H.real_name], currently in [get_area(H.loc)]. ")
if(killthem)
- to_chat(hunter_mob, "If you kill [H.p_them()], [H.p_they()] cannot be revived.");
+ to_chat(hunter_mob, "If you kill [H.p_them()], [H.p_they()] cannot be revived.")
hunter_mob.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/atom_hud/antag/tatorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
tatorhud.join_hud(hunter_mob)
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index e2da701cf4d..c4eabef3eae 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -430,7 +430,7 @@
else if(expression[start + 1] == "\[" && islist(v))
var/list/L = v
var/index = SDQL_expression(source, expression[start + 2])
- if(isnum(index) && (!IsInteger(index) || L.len < index))
+ if(isnum(index) && (!ISINTEGER(index) || L.len < index))
to_chat(world, "Invalid list index: [index]")
return null
return L[index]
@@ -444,9 +444,9 @@
if(object == world) // Global proc.
procname = "/proc/[procname]"
- return call(procname)(arglist(new_args))
+ return (WrapAdminProcCall(GLOBAL_PROC, procname, new_args))
- return call(object, procname)(arglist(new_args))
+ return (WrapAdminProcCall(object, procname, new_args))
/proc/SDQL2_tokenize(query_text)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 8ac9c4fd2b0..f74b8c9d030 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -165,7 +165,7 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
for(var/client/X in GLOB.admins)
- admin_number_total++;
+ admin_number_total++
var/invalid = 0
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
admin_number_ignored++
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 32355cd17fd..dba9a5c26aa 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -19,7 +19,7 @@
var/list/client/targets[0]
for(var/client/T)
if(T.mob)
- if(istype(T.mob, /mob/new_player))
+ if(isnewplayer(T.mob))
targets["(New Player) - [T]"] = T
else if(istype(T.mob, /mob/dead/observer))
targets["[T.mob.name](Ghost) - [T]"] = T
@@ -42,7 +42,7 @@
var/list/client/targets[0]
for(var/client/T)
if(T.mob)
- if(istype(T.mob, /mob/new_player))
+ if(isnewplayer(T.mob))
targets["[T] - (New Player)"] = T
else if(istype(T.mob, /mob/dead/observer))
targets["[T] - [T.mob.name](Ghost)"] = T
@@ -261,7 +261,7 @@
/datum/pm_tracker
var/current_title = ""
var/open = FALSE
- var/list/pms = list()
+ var/list/datum/pm_convo/pms = list()
var/show_archived = FALSE
var/window_id = "pms_window"
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index a0e8b4b9088..5a0425af30a 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -78,5 +78,5 @@
C.verbs -= msay
to_chat(C, "Mentor chat has been disabled.")
- admin_log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
+ log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
feedback_add_details("admin_verb", "TMC")
diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm
index 087a90eebe6..ed8533dc9d5 100644
--- a/code/modules/admin/verbs/atmosdebug.dm
+++ b/code/modules/admin/verbs/atmosdebug.dm
@@ -1,7 +1,6 @@
/client/proc/atmosscan()
set category = "Mapping"
set name = "Check Piping"
- set background = 1
if(!src.holder)
to_chat(src, "Only administrators may use this command.")
return
@@ -12,17 +11,18 @@
to_chat(usr, "Checking for disconnected pipes...")
//all plumbing - yes, some things might get stated twice, doesn't matter.
- for(var/obj/machinery/atmospherics/plumbing in world)
+ for(var/thing in SSair.atmos_machinery)
+ var/obj/machinery/atmospherics/plumbing = thing
if(plumbing.nodealert)
to_chat(usr, "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])")
//Manifolds
- for(var/obj/machinery/atmospherics/pipe/manifold/pipe in world)
+ for(var/obj/machinery/atmospherics/pipe/manifold/pipe in SSair.atmos_machinery)
if(!pipe.node1 || !pipe.node2 || !pipe.node3)
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
//Pipes
- for(var/obj/machinery/atmospherics/pipe/simple/pipe in world)
+ for(var/obj/machinery/atmospherics/pipe/simple/pipe in SSair.atmos_machinery)
if(!pipe.node1 || !pipe.node2)
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 5ec8ecde253..43db66cabc5 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -85,18 +85,80 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return
message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
+ returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
- returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
+ returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
to_chat(usr, "[procname] returned: [!isnull(returnval) ? returnval : "null"]")
feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+// All these vars are related to proc call protection
+// If you add more of these, for the love of fuck, protect them
+
+/// Who is currently calling procs
GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
+/// How many procs have been called
+GLOBAL_VAR_INIT(AdminProcCallCount, 0)
+GLOBAL_PROTECT(AdminProcCallCount)
+/// UID of the admin who last called
+GLOBAL_VAR(LastAdminCalledTargetUID)
+GLOBAL_PROTECT(LastAdminCalledTargetUID)
+/// Last target to have a proc called on it
+GLOBAL_VAR(LastAdminCalledTarget)
+GLOBAL_PROTECT(LastAdminCalledTarget)
+/// Last proc called
+GLOBAL_VAR(LastAdminCalledProc)
+GLOBAL_PROTECT(LastAdminCalledProc)
+/// List to handle proc call spam prevention
+GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
+GLOBAL_PROTECT(AdminProcCallSpamPrevention)
+
+
+// Wrapper for proccalls where the datum is flagged as vareditted
+/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
+ if(target && procname == "Del")
+ to_chat(usr, "Calling Del() is not allowed")
+ return
+
+ if(target != GLOBAL_PROC && !target.CanProcCall(procname))
+ to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
+ return
+ var/current_caller = GLOB.AdminProcCaller
+ var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
+ if(!ckey)
+ CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
+ if(current_caller && current_caller != ckey)
+ if(!GLOB.AdminProcCallSpamPrevention[ckey])
+ to_chat(usr, "Another set of admin called procs are still running, your proc will be run after theirs finish.")
+ GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
+ UNTIL(!GLOB.AdminProcCaller)
+ to_chat(usr, "Running your proc")
+ GLOB.AdminProcCallSpamPrevention -= ckey
+ else
+ UNTIL(!GLOB.AdminProcCaller)
+ GLOB.LastAdminCalledProc = procname
+ if(target != GLOBAL_PROC)
+ GLOB.LastAdminCalledTargetUID = target.UID()
+ GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
+ ++GLOB.AdminProcCallCount
+ . = world.WrapAdminProcCall(target, procname, arguments)
+ if(--GLOB.AdminProcCallCount == 0)
+ GLOB.AdminProcCaller = null
+
+//adv proc call this, ya nerds
+/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
+ if(target == GLOBAL_PROC)
+ return call(procname)(arglist(arguments))
+ else if(target != world)
+ return call(target, procname)(arglist(arguments))
+ else
+ to_chat(usr, "Call to world/proc/[procname] blocked: Advanced ProcCall detected.")
+ message_admins("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
+ log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]l")
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
@@ -131,7 +193,7 @@ GLOBAL_PROTECT(AdminProcCaller)
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
spawn()
- var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
+ var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
to_chat(src, "[procname] returned: [!isnull(returnval) ? returnval : "null"]")
feedback_add_details("admin_verb","DPC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -251,7 +313,7 @@ GLOBAL_PROTECT(AdminProcCaller)
alert("That mob doesn't seem to exist, close the panel and try again.")
return
- if(istype(M, /mob/new_player))
+ if(isnewplayer(M))
alert("The mob must not be a new_player.")
return
@@ -382,7 +444,7 @@ GLOBAL_PROTECT(AdminProcCaller)
if(!check_rights(R_DEBUG))
return
- //This gets a confirmation check because it's way easier to accidentally hit this and delete things than it is with del-all
+ //This gets a confirmation check because it's way easier to accidentally hit this and delete things than it is with qdel-all
var/confirm = alert("This will delete ALL Singularities and Tesla orbs except for any that are on away mission z-levels or the centcomm z-level. Are you sure you want to delete them?", "Confirm Panic Button", "Yes", "No")
if(confirm != "Yes")
return
@@ -428,7 +490,7 @@ GLOBAL_PROTECT(AdminProcCaller)
id.icon_state = "gold"
id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
else
- var/obj/item/card/id/id = new/obj/item/card/id(M);
+ var/obj/item/card/id/id = new/obj/item/card/id(M)
id.icon_state = "gold"
id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
id.registered_name = H.real_name
@@ -487,7 +549,8 @@ GLOBAL_PROTECT(AdminProcCaller)
for(var/area/A in world)
areas_all |= A.type
- for(var/obj/machinery/power/apc/APC in world)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/APC = thing
var/area/A = get_area(APC)
if(!A)
continue
@@ -496,7 +559,8 @@ GLOBAL_PROTECT(AdminProcCaller)
else
areas_with_multiple_APCs |= A.type
- for(var/obj/machinery/alarm/alarm in world)
+ for(var/thing in GLOB.air_alarms)
+ var/obj/machinery/alarm/alarm = thing
var/area/A = get_area(alarm)
if(!A)
continue
@@ -505,31 +569,31 @@ GLOBAL_PROTECT(AdminProcCaller)
else
areas_with_multiple_air_alarms |= A.type
- for(var/obj/machinery/requests_console/RC in world)
+ for(var/obj/machinery/requests_console/RC in GLOB.machines)
var/area/A = get_area(RC)
if(!A)
continue
areas_with_RC |= A.type
- for(var/obj/machinery/light/L in world)
+ for(var/obj/machinery/light/L in GLOB.machines)
var/area/A = get_area(L)
if(!A)
continue
areas_with_light |= A.type
- for(var/obj/machinery/light_switch/LS in world)
+ for(var/obj/machinery/light_switch/LS in GLOB.machines)
var/area/A = get_area(LS)
if(!A)
continue
areas_with_LS |= A.type
- for(var/obj/item/radio/intercom/I in world)
+ for(var/obj/item/radio/intercom/I in GLOB.global_radios)
var/area/A = get_area(I)
if(!A)
continue
areas_with_intercom |= A.type
- for(var/obj/machinery/camera/C in world)
+ for(var/obj/machinery/camera/C in GLOB.machines)
var/area/A = get_area(C)
if(!A)
continue
@@ -579,7 +643,7 @@ GLOBAL_PROTECT(AdminProcCaller)
for(var/areatype in areas_without_camera)
to_chat(world, "* [areatype]")
-/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in GLOB.mob_list)
+/client/proc/cmd_admin_dress(mob/living/carbon/human/M in GLOB.human_list)
set category = "Event"
set name = "Select equipment"
@@ -716,23 +780,25 @@ GLOBAL_PROTECT(AdminProcCaller)
if(!check_rights(R_DEBUG))
return
- switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Silicons","Clients","Respawnable Mobs"))
+ switch(input("Which list?") in list("Players", "Admins", "Mobs", "Living Mobs", "Alive Mobs", "Dead Mobs", "Silicons", "Clients", "Respawnable Mobs"))
if("Players")
- to_chat(usr, jointext(GLOB.player_list,","))
+ to_chat(usr, jointext(GLOB.player_list, ","))
if("Admins")
- to_chat(usr, jointext(GLOB.admins,","))
+ to_chat(usr, jointext(GLOB.admins, ","))
if("Mobs")
- to_chat(usr, jointext(GLOB.mob_list,","))
+ to_chat(usr, jointext(GLOB.mob_list, ","))
if("Living Mobs")
- to_chat(usr, jointext(GLOB.living_mob_list,","))
+ to_chat(usr, jointext(GLOB.mob_living_list, ","))
+ if("Alive Mobs")
+ to_chat(usr, jointext(GLOB.alive_mob_list, ","))
if("Dead Mobs")
- to_chat(usr, jointext(GLOB.dead_mob_list,","))
+ to_chat(usr, jointext(GLOB.dead_mob_list, ","))
if("Silicons")
- to_chat(usr, jointext(GLOB.silicon_mob_list,","))
+ to_chat(usr, jointext(GLOB.silicon_mob_list, ","))
if("Clients")
- to_chat(usr, jointext(GLOB.clients,","))
+ to_chat(usr, jointext(GLOB.clients, ","))
if("Respawnable Mobs")
- to_chat(usr, jointext(GLOB.respawnable_list,","))
+ to_chat(usr, jointext(GLOB.respawnable_list, ","))
/client/proc/cmd_display_del_log()
set category = "Debug"
@@ -812,27 +878,12 @@ GLOBAL_PROTECT(AdminProcCaller)
else
alert("Invalid mob")
-/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.
- SSnanoui.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()
-
/client/proc/view_runtimes()
set category = "Debug"
set name = "View Runtimes"
set desc = "Open the Runtime Viewer"
- if(!check_rights(R_DEBUG))
+ if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
return
GLOB.error_cache.showTo(usr)
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index 92bcfa25c3a..78f2647e429 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -15,9 +15,7 @@
if(T.active_hotspot)
burning = 1
- to_chat(usr, "@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("BURNING"):(null)]")
- for(var/datum/gas/trace_gas in GM.trace_gases)
- to_chat(usr, "[trace_gas.type]: [trace_gas.moles]")
+ to_chat(usr, "@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] N2O: [GM.sleeping_agent] Agent B: [GM.agent_b] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("BURNING"):(null)]")
message_admins("[key_name_admin(usr)] has checked the air status of [target]")
log_admin("[key_name(usr)] has checked the air status of [target]")
@@ -85,7 +83,7 @@
var/output = "Radio Report"
for(var/fq in SSradio.frequencies)
output += "Freq: [fq] "
- var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq]
+ var/datum/radio_frequency/fqs = SSradio.frequencies[fq]
if(!fqs)
output += " ERROR "
continue
diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm
index f775ba0e917..0f52680acea 100644
--- a/code/modules/admin/verbs/freeze.dm
+++ b/code/modules/admin/verbs/freeze.dm
@@ -5,121 +5,99 @@
//////Allows admin's to right click on any mob/mech and freeze them in place.///
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-GLOBAL_LIST_EMPTY(frozen_mob_list)
-/client/proc/freeze(var/mob/living/M as mob in GLOB.mob_list)
+
+GLOBAL_LIST_EMPTY(frozen_atom_list) // A list of admin-frozen atoms.
+
+/client/proc/freeze(atom/movable/M)
set name = "Freeze"
set category = null
if(!check_rights(R_ADMIN))
return
- if(!istype(M))
- return
+ M.admin_Freeze(src)
- if(M in GLOB.frozen_mob_list)
- M.admin_unFreeze(src)
- else
- M.admin_Freeze(src)
+/// Created here as a base proc. Override as needed for any type of object or mob you want able to be frozen.
+/atom/movable/proc/admin_Freeze(client/admin)
+ to_chat(admin, "Freeze is not able to be called on this type of object.You have been frozen by [admin]")
- message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]")
- log_admin("[key_name(admin)] froze [key_name(src)]")
+/mob/living/admin_Freeze(client/admin, skip_overlays = FALSE, mech = null)
+ if(!istype(admin))
+ return
- var/obj/effect/overlay/adminoverlay/AO = new
- if(skip_overlays)
- overlays += AO
+ if(!(src in GLOB.frozen_atom_list))
+ GLOB.frozen_atom_list += src
- anchored = TRUE
- canmove = FALSE
- admin_prev_sleeping = sleeping
- AdjustSleeping(20000)
- frozen = AO
- if(!(src in GLOB.frozen_mob_list))
- GLOB.frozen_mob_list += src
+ var/obj/effect/overlay/adminoverlay/AO = new
+ if(skip_overlays)
+ overlays += AO
-/mob/living/proc/admin_unFreeze(client/admin, skip_overlays = FALSE)
- if(istype(admin))
- to_chat(src, "You have been unfrozen by [admin]")
- message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]")
- log_admin("[key_name(admin)] unfroze [key_name(src)]")
+ anchored = TRUE
+ canmove = FALSE
+ admin_prev_sleeping = sleeping
+ AdjustSleeping(20000)
+ frozen = AO
- if(skip_overlays)
- overlays -= frozen
+ else
+ GLOB.frozen_atom_list -= src
- anchored = FALSE
- canmove = TRUE
- frozen = null
- SetSleeping(admin_prev_sleeping)
- admin_prev_sleeping = null
- if(src in GLOB.frozen_mob_list)
- GLOB.frozen_mob_list -= src
+ if(skip_overlays)
+ overlays -= frozen
+ anchored = FALSE
+ canmove = TRUE
+ frozen = null
+ SetSleeping(admin_prev_sleeping)
+ admin_prev_sleeping = null
+
+ to_chat(src, "You have been [frozen ? "frozen" : "unfrozen"] by [admin]")
+ message_admins("[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] [key_name_admin(src)] [mech ? "in a [mech]" : ""]")
+ log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] [key_name(src)] [mech ? "in a [mech]" : ""]")
update_icons()
+ return frozen
+
/mob/living/simple_animal/slime/admin_Freeze(admin)
- ..(admin)
- adjustHealth(1000) //arbitrary large value
-
-/mob/living/simple_animal/slime/admin_unFreeze(admin)
- ..(admin)
- revive()
-
+ if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen.
+ adjustHealth(1000) //arbitrary large value
+ else
+ revive()
/mob/living/simple_animal/var/admin_prev_health = null
/mob/living/simple_animal/admin_Freeze(admin)
- ..(admin)
- admin_prev_health = health
- health = 0
-
-/mob/living/simple_animal/admin_unFreeze(admin)
- ..(admin)
- revive()
- overlays.Cut()
+ if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen.
+ admin_prev_health = health
+ health = 0
+ else
+ revive()
+ overlays.Cut()
//////////////////////////Freeze Mech
-/client/proc/freezemecha(var/obj/mecha/O as obj in GLOB.mechas_list)
- set name = "Freeze Mech"
- set category = null
-
- if(!check_rights(R_ADMIN))
- return
-
- var/obj/mecha/M = O
- if(!istype(M,/obj/mecha))
- to_chat(src, "This can only be used on mechs!")
- return
+/obj/mecha/admin_Freeze(client/admin)
+ var/obj/effect/overlay/adminoverlay/freeze_overlay = new
+ if(!frozen)
+ GLOB.frozen_atom_list += src
+ frozen = TRUE
+ overlays += freeze_overlay
else
- if(usr)
- if(usr.client)
- if(usr.client.holder)
- var/adminomaly = new/obj/effect/overlay/adminoverlay
- if(M.can_move == 1)
- M.can_move = 0
- M.overlays += adminomaly
- if(M.occupant)
- to_chat(M.occupant, "You have been frozen by [key]")
- message_admins("[key_name_admin(usr)] froze [key_name(M.occupant)] in a [M.name]")
- log_admin("[key_name(usr)] froze [key_name(M.occupant)] in a [M.name]")
- else
- message_admins("[key_name_admin(usr)] froze an empty [M.name]")
- log_admin("[key_name(usr)] froze an empty [M.name]")
- else if(M.can_move == 0)
- M.can_move = 1
- M.overlays -= adminomaly
- if(M.occupant)
- to_chat(M.occupant, "You have been unfrozen by [key]")
- message_admins("[key_name_admin(usr)] unfroze [key_name(M.occupant)] in a [M.name]")
- log_admin("[key_name(usr)] unfroze [key_name(M.occupant)] in a [M.name]")
- else
- message_admins("[key_name_admin(usr)] unfroze an empty [M.name]")
- log_admin("[key_name(usr)] unfroze an empty [M.name]")
+ GLOB.frozen_atom_list -= src
+ frozen = FALSE
+ overlays -= freeze_overlay
+
+ if(occupant)
+ occupant.admin_Freeze(admin, mech = name) // We also want to freeze the driver of the mech.
+ else
+ message_admins("[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] an empty [name]")
+ log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] an empty [name]")
diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm
index cad93e8b880..37afe35ef6a 100644
--- a/code/modules/admin/verbs/gimmick_team.dm
+++ b/code/modules/admin/verbs/gimmick_team.dm
@@ -27,7 +27,7 @@
if(!themission)
alert("No mission specified. Aborting.")
return
- var/admin_outfits = subtypesof(/datum/outfit/admin)
+ var/admin_outfits = subtypesof(/datum/outfit/admin) + list(/datum/outfit/naked)
var/outfit_list = list()
for(var/type in admin_outfits)
var/datum/outfit/admin/O = type
diff --git a/code/modules/admin/verbs/honksquad.dm b/code/modules/admin/verbs/honksquad.dm
index 8c8d46ec97b..5107ce7e22c 100644
--- a/code/modules/admin/verbs/honksquad.dm
+++ b/code/modules/admin/verbs/honksquad.dm
@@ -48,7 +48,8 @@ GLOBAL_VAR_INIT(sent_honksquad, 0)
commandos += candidate//Add their ghost to commandos.
//Spawns HONKsquad and equips them.
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(honksquad_number<=0) break
if(L.name == "HONKsquad")
honk_leader_selected = honksquad_number == 1?1:0
diff --git a/code/modules/admin/verbs/infiltratorteam_syndicate.dm b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
index 459f2b8fb4b..54ddf85045e 100644
--- a/code/modules/admin/verbs/infiltratorteam_syndicate.dm
+++ b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
@@ -66,7 +66,8 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
var/list/sit_spawns = list()
var/list/sit_spawns_leader = list()
var/list/sit_spawns_mgmt = list()
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Syndicate-Infiltrator")
sit_spawns += L
if(L.name == "Syndicate-Infiltrator-Leader")
diff --git a/code/modules/admin/verbs/logging_view.dm b/code/modules/admin/verbs/logging_view.dm
index 976554a0375..cafaab8f1d7 100644
--- a/code/modules/admin/verbs/logging_view.dm
+++ b/code/modules/admin/verbs/logging_view.dm
@@ -18,3 +18,4 @@ GLOBAL_LIST_INIT(open_logging_views, list())
cur_view.add_mobs(mobs_to_add)
cur_view.show_ui(usr)
+
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 10ad31ef410..5e05b8ecebd 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -118,7 +118,7 @@ GLOBAL_VAR_INIT(intercom_range_display_status, 0)
qdel(M)
if(GLOB.intercom_range_display_status)
- for(var/obj/item/radio/intercom/I in world)
+ for(var/obj/item/radio/intercom/I in GLOB.global_radios)
for(var/turf/T in orange(7,I))
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
if(!(F in view(7,I.loc)))
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index 6a1efba4c93..079446b0994 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -543,7 +543,7 @@ GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "step_size", "bound_h
var/var_value
if(param_var_name)
- if(!param_var_name in O.vars)
+ if(!(param_var_name in O.vars))
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])")
return
variable = param_var_name
@@ -627,6 +627,7 @@ GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "step_size", "bound_h
if(!O.vv_edit_var(variable, var_new))
to_chat(src, "Your edit was rejected by the object.")
return
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args)
log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]")
log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_new]")
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [var_new]"
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 57f7cad31c4..3e89a6ac18d 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -267,7 +267,7 @@ client/proc/one_click_antag()
var/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd")
synd_mind.current.client.images += I
- for(var/obj/machinery/nuclearbomb/bomb in world)
+ for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
bomb.r_code = nuke_code // All the nukes are set to this code.
return 1
@@ -455,7 +455,8 @@ client/proc/one_click_antag()
if(candidates.len)
var/raiders = min(antnum, candidates.len)
//Spawns vox raiders and equips them.
- for(var/obj/effect/landmark/L in world)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "voxstart")
if(raiders<=0)
break
@@ -583,7 +584,8 @@ client/proc/one_click_antag()
var/teamOneMembers = 5
var/teamTwoMembers = 5
var/datum/preferences/A = new()
- for(var/obj/effect/landmark/L in world)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "tdome1")
if(teamOneMembers<=0)
break
diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm
index e51f6da991a..9f2579ad162 100644
--- a/code/modules/admin/verbs/onlyone.dm
+++ b/code/modules/admin/verbs/onlyone.dm
@@ -84,7 +84,7 @@
var/obj/item/slot_item_hand = H.get_item_by_slot(slot_r_hand)
H.unEquip(slot_item_hand)
- var /obj/item/multisword/pure_evil/multi = new(H)
+ var/obj/item/multisword/pure_evil/multi = new(H)
H.equip_to_slot_or_del(multi, slot_r_hand)
var/obj/item/card/id/W = new(H)
diff --git a/code/modules/admin/verbs/onlyoneteam.dm b/code/modules/admin/verbs/onlyoneteam.dm
index c0847d6ff7e..974b65e05d2 100644
--- a/code/modules/admin/verbs/onlyoneteam.dm
+++ b/code/modules/admin/verbs/onlyoneteam.dm
@@ -73,20 +73,21 @@
..()
if((ishuman(hit_atom)))
var/mob/living/carbon/human/H = hit_atom
- if(H.r_hand == src) return
- if(H.l_hand == src) return
- var/mob/A = H.LAssailant
+ if(H.r_hand == src)
+ return
+ if(H.l_hand == src)
+ return
+ var/mob/A = thrownby
if((H in GLOB.team_alpha) && (A in GLOB.team_alpha))
to_chat(A, "He's on your team!")
return
else if((H in GLOB.team_bravo) && (A in GLOB.team_bravo))
to_chat(A, "He's on your team!")
return
- else if(!A in GLOB.team_alpha && !A in GLOB.team_bravo)
+ else if(!(A in GLOB.team_alpha) && !(A in GLOB.team_bravo))
to_chat(A, "You're not part of the dodgeball game, sorry!")
return
else
playsound(src, 'sound/items/dodgeball.ogg', 50, 1)
visible_message("[H] HAS BEEN ELIMINATED!")
H.melt()
- return
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index 6ec103cccc9..ed01bc822a7 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(sounds_cache)
set name = "Play Server Sound"
if(!check_rights(R_SOUNDS)) return
- var/list/sounds = file2list("sound/serversound_list.txt");
+ var/list/sounds = file2list("sound/serversound_list.txt")
sounds += GLOB.sounds_cache
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
@@ -71,7 +71,7 @@ GLOBAL_LIST_EMPTY(sounds_cache)
var/A = alert("This will play a sound at every intercomm, are you sure you want to continue? This works best with short sounds, beware.","Warning","Yep","Nope")
if(A != "Yep") return
- var/list/sounds = file2list("sound/serversound_list.txt");
+ var/list/sounds = file2list("sound/serversound_list.txt")
sounds += GLOB.sounds_cache
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index a8136655d8f..a65884369a1 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -533,7 +533,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/list/mobs = list()
var/list/ghosts = list()
var/list/sortmob = sortAtom(GLOB.mob_list) // get the mob list.
- /var/any=0
+ var/any=0
for(var/mob/dead/observer/M in sortmob)
mobs.Add(M) //filter it where it's only ghosts
any = 1 //if no ghosts show up, any will just be 0
@@ -627,7 +627,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
print_command_report(input, "[command_name()] Update")
if("No")
//same thing as the blob stuff - it's not public, so it's classified, dammit
- GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.");
+ GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.")
print_command_report(input, "Classified [command_name()] Update")
else
return
@@ -826,7 +826,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
SSshuttle.emergency.canRecall = FALSE
- SSshuttle.emergency.request()
+ if(seclevel2num(get_security_level()) >= SEC_LEVEL_RED)
+ SSshuttle.emergency.request(coefficient = 0.5, redAlert = TRUE)
+ else
+ SSshuttle.emergency.request()
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
@@ -954,7 +957,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(confirm != "Yes")
return
- GLOB.nttc_config.reset()
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ C.nttc.reset()
+
log_admin("[key_name(usr)] reset NTTC scripts.")
message_admins("[key_name_admin(usr)] reset NTTC scripts.")
feedback_add_details("admin_verb","RAT2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -977,7 +982,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/role_string
var/obj_count = 0
var/obj_string = ""
- for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
if(!isLivingSSD(H))
continue
mins_ssd = round((world.time - H.last_logout) / 600)
@@ -1014,7 +1020,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
msg += "AFK Players:
"
msg += "
Key
Real Name
Job
Mins AFK
Special Role
Area
PPN
Cryo
"
var/mins_afk
- for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
if(H.client == null || H.stat == DEAD) // No clientless or dead
continue
mins_afk = round(H.client.inactivity / 600)
diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm
index 25874d03360..0b84c96e71a 100644
--- a/code/modules/admin/verbs/striketeam.dm
+++ b/code/modules/admin/verbs/striketeam.dm
@@ -30,7 +30,7 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
// Find the nuclear auth code
var/nuke_code
var/temp_code
- for(var/obj/machinery/nuclearbomb/N in world)
+ for(var/obj/machinery/nuclearbomb/N in GLOB.machines)
temp_code = text2num(N.r_code)
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
nuke_code = N.r_code
@@ -48,7 +48,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
var/commando_number = COMMANDOS_POSSIBLE //for selecting a leader
var/is_leader = TRUE // set to FALSE after leader is spawned
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(commando_number <= 0)
break
@@ -109,7 +110,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
commando_number--
//Spawns the rest of the commando gear.
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Commando_Manual")
//new /obj/item/gun/energy/pulse_rifle(L.loc)
var/obj/item/paper/P = new(L.loc)
@@ -120,7 +122,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
P.stamp(stamp)
qdel(stamp)
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "Commando-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
qdel(L)
@@ -158,6 +161,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
var/obj/item/radio/R = new /obj/item/radio/headset/alt(src)
R.set_frequency(DTH_FREQ)
+ R.requires_tcomms = FALSE
+ R.instant = TRUE
equip_to_slot_or_del(R, slot_l_ear)
if(is_leader)
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm
index 73ee5edb82d..12df7467cbc 100644
--- a/code/modules/admin/verbs/striketeam_syndicate.dm
+++ b/code/modules/admin/verbs/striketeam_syndicate.dm
@@ -38,7 +38,7 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
// Find the nuclear auth code
var/nuke_code
var/temp_code
- for(var/obj/machinery/nuclearbomb/N in world)
+ for(var/obj/machinery/nuclearbomb/N in GLOB.machines)
temp_code = text2num(N.r_code)
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
nuke_code = N.r_code
@@ -53,7 +53,8 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
GLOB.sent_syndicate_strike_team = 1
//Spawns commandos and equips them.
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(syndicate_commando_number <= 0)
break
diff --git a/code/modules/admin/verbs/toggledebugverbs.dm b/code/modules/admin/verbs/toggledebugverbs.dm
index 216f5c3e4b0..38b49869298 100644
--- a/code/modules/admin/verbs/toggledebugverbs.dm
+++ b/code/modules/admin/verbs/toggledebugverbs.dm
@@ -17,8 +17,6 @@ GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list(
/client/proc/print_jobban_old,
/client/proc/print_jobban_old_filter,
/client/proc/forceEvent,
- /client/proc/nanomapgen_DumpImage,
- /client/proc/reload_nanoui_resources,
/client/proc/admin_redo_space_transitions,
/client/proc/make_turf_space_map,
/client/proc/vv_by_ref
diff --git a/code/modules/alarm/alarm.dm b/code/modules/alarm/alarm.dm
index 798c5176770..752d3232d23 100644
--- a/code/modules/alarm/alarm.dm
+++ b/code/modules/alarm/alarm.dm
@@ -50,7 +50,7 @@
sources_assoc[source] = AS
// Currently only non-0 durations can be altered (normal alarms VS EMP blasts)
if(AS.duration)
- duration = SecondsToTicks(duration)
+ duration = duration SECONDS
AS.duration = duration
AS.severity = severity
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index beefc41735b..8e29326632f 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -194,7 +194,7 @@
to_chat(user, "The demons do not respond to your summon. Perhaps you should try again later.")
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
- var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
+ var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
S.vialspawned = TRUE
S.holder = holder
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index e13fb701317..ee23ea35d98 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -41,9 +41,8 @@
A.common_radio.channels.Remove("Syndicate") // De-traitored AIs can still state laws over the syndicate channel without this
A.laws.sorted_laws = A.laws.inherent_laws.Copy() // AI's 'notify laws' button will still state a law 0 because sorted_laws contains it
A.show_laws()
- A.malf_picker.remove_malf_verbs(A)
- A.verbs -= /mob/living/silicon/ai/proc/choose_modules
- qdel(A.malf_picker)
+ A.remove_malf_abilities()
+ QDEL_NULL(A.malf_picker)
if(owner.som)
var/datum/mindslaves/slaved = owner.som
@@ -400,7 +399,7 @@
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
- var message = " The code phrases were:[phrases] \
+ var/message = " The code phrases were:[phrases] \
The code responses were:[responses] "
return message
diff --git a/code/modules/arcade/claw_game.dm b/code/modules/arcade/claw_game.dm
index 822011be3f6..6ee5c83b89c 100644
--- a/code/modules/arcade/claw_game.dm
+++ b/code/modules/arcade/claw_game.dm
@@ -58,7 +58,7 @@ GLOBAL_VAR(claw_game_html)
atom_say("WINNER!")
new /obj/item/toy/prizeball(get_turf(src))
playsound(src.loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
- addtimer(CALLBACK(src, .update_icon), 10)
+ addtimer(CALLBACK(src, .proc/update_icon), 10)
/obj/machinery/arcade/claw/start_play(mob/user as mob)
..()
diff --git a/code/modules/arcade/mob_hunt/battle_computer.dm b/code/modules/arcade/mob_hunt/battle_computer.dm
index 94337a5cfac..cb144c99f01 100644
--- a/code/modules/arcade/mob_hunt/battle_computer.dm
+++ b/code/modules/arcade/mob_hunt/battle_computer.dm
@@ -80,7 +80,7 @@
/obj/machinery/computer/mob_battle_terminal/proc/eject_card(override = 0)
if(!override)
if(ready && SSmob_hunt.battle_turn != team)
- audible_message("You can't recall on your rival's turn!", null, 2)
+ atom_say("You can't recall on your rival's turn!")
return
card.mob_data = mob_info
mob_info = null
@@ -202,7 +202,7 @@
start_battle()
else if(option == 2)
ready = 0
- audible_message("[team] Player cancels their battle challenge.", null, 5)
+ atom_say("[team] Player cancels their battle challenge.")
updateUsrDialog()
@@ -246,7 +246,7 @@
var/message = "[mob_info.mob_name] attacks!"
if(mob_info.nickname)
message = "[mob_info.nickname] attacks!"
- audible_message(message, null, 5)
+ atom_say(message)
SSmob_hunt.launch_attack(team, mob_info.get_raw_damage(), mob_info.get_attack_type())
/obj/machinery/computer/mob_battle_terminal/proc/start_battle()
@@ -255,7 +255,7 @@
if(!card) //don't do anything if there isn't a card inserted
return
ready = 1
- audible_message("[team] Player is ready for battle! Waiting for rival...", null, 5)
+ atom_say("[team] Player is ready for battle! Waiting for rival...")
SSmob_hunt.start_check()
/obj/machinery/computer/mob_battle_terminal/proc/receive_attack(raw_damage, datum/mob_type/attack_type)
@@ -268,7 +268,7 @@
SSmob_hunt.end_turn()
/obj/machinery/computer/mob_battle_terminal/proc/surrender()
- audible_message("[team] Player surrenders the battle!", null, 5)
+ atom_say("[team] Player surrenders the battle!")
SSmob_hunt.end_battle(team, 1)
//////////////////////////////
diff --git a/code/modules/arcade/mob_hunt/mob_avatar.dm b/code/modules/arcade/mob_hunt/mob_avatar.dm
index 89eda41be7c..d1077bc81e1 100644
--- a/code/modules/arcade/mob_hunt/mob_avatar.dm
+++ b/code/modules/arcade/mob_hunt/mob_avatar.dm
@@ -55,7 +55,7 @@
var/datum/data/pda/app/mob_hunter_game/client = P.current_app
var/total_catch_mod = client.catch_mod + catch_mod //negative values decrease the chance of the mob running, positive values makes it more likely to flee
if(!client.connected) //must be connected to attempt captures
- P.audible_message("[bicon(P)] No server connection. Capture aborted.", null, 4)
+ P.atom_say("No server connection. Capture aborted.")
return
if(mob_info.is_trap) //traps work even if you ran into them before, which is why this is before the clients_encountered check
@@ -79,7 +79,7 @@
return
else //deal with the new hunter by either running away or getting caught
clients_encountered += client
- var/message = "[bicon(P)] "
+ var/message = null
var/effective_run_chance = mob_info.run_chance + total_catch_mod
if((effective_run_chance > 0) && prob(effective_run_chance))
message += "Capture failed! [name] escaped [P.owner ? "from [P.owner]" : "from this hunter"]!"
@@ -91,7 +91,7 @@
else
message += "Capture error! Try again."
clients_encountered -= client //if the capture registration failed somehow, let them have another chance with this mob
- P.audible_message(message, null, 4)
+ P.atom_say(message)
/obj/effect/nanomob/proc/despawn()
if(SSmob_hunt)
diff --git a/code/modules/arcade/mob_hunt/mob_datums.dm b/code/modules/arcade/mob_hunt/mob_datums.dm
index a50fab183e6..25a4569ede9 100644
--- a/code/modules/arcade/mob_hunt/mob_datums.dm
+++ b/code/modules/arcade/mob_hunt/mob_datums.dm
@@ -139,7 +139,7 @@
for(var/areapath in typesof(A))
possible_areas[areapath] -= 2
//removes "bad areas" which shouldn't be on-station but are subtypes of station areas. probably should the unused ones and consider repathing the rest
- var/list/bad_areas = list(subtypesof(/area/construction), /area/solar/derelict_starboard, /area/solar/derelict_aft, /area/solar/constructionsite)
+ var/list/bad_areas = list(subtypesof(/area/construction), /area/solar/derelict_starboard, /area/solar/derelict_aft)
for(var/A in bad_areas)
possible_areas -= A
//weight check, remove negative or zero weight areas from the list, then return the list.
diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm
index 827e7893396..5fea7baa019 100644
--- a/code/modules/assembly/assembly.dm
+++ b/code/modules/assembly/assembly.dm
@@ -59,8 +59,7 @@
cooldown--
if(cooldown <= 0)
return FALSE
- spawn(10)
- process_cooldown()
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
return TRUE
/obj/item/assembly/Destroy()
@@ -94,8 +93,7 @@
if(!secured || cooldown > 0)
return FALSE
cooldown = 2
- spawn(10)
- process_cooldown()
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
return TRUE
/obj/item/assembly/toggle_secure()
diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm
index a83df5501c9..a0a7c43a7a9 100644
--- a/code/modules/assembly/health.dm
+++ b/code/modules/assembly/health.dm
@@ -55,7 +55,7 @@
health_scan = M.health
if(health_scan <= alarm_health)
pulse()
- audible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
+ audible_message("[bicon(src)] *beep* *beep*")
toggle_scan()
return
return
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 19263e010ab..9de2f32ed6f 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -127,13 +127,12 @@
/obj/item/assembly/infra/proc/trigger_beam()
if(!secured || !on || cooldown > 0)
return FALSE
- pulse(0)
- audible_message("[bicon(src)] *beep* *beep*", null, 3)
+ cooldown = 2
+ pulse(FALSE)
+ audible_message("[bicon(src)] *beep* *beep*", hearing_distance = 3)
if(first)
qdel(first)
- cooldown = 2
- spawn(10)
- process_cooldown()
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
/obj/item/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel
if(!secured) return
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index 9b4c9b38677..35e80e53d18 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -89,7 +89,7 @@
/obj/item/assembly/mousetrap/attack_hand(mob/living/user)
if(armed)
- if((user.getBrainLoss() >= 60 || CLUMSY in user.mutations) && prob(50))
+ if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))
var/which_hand = "l_hand"
if(!user.hand)
which_hand = "r_hand"
diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm
index 7e777f235b1..caefabcb1f8 100644
--- a/code/modules/assembly/proximity.dm
+++ b/code/modules/assembly/proximity.dm
@@ -47,11 +47,10 @@
/obj/item/assembly/prox_sensor/proc/sense()
if(!secured || !scanning || cooldown > 0)
return FALSE
- pulse(0)
- visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
cooldown = 2
- spawn(10)
- process_cooldown()
+ pulse(FALSE)
+ visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
/obj/item/assembly/prox_sensor/process()
if(timing && (time >= 0))
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index f774d28921f..2759d12c21a 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -41,8 +41,7 @@
if(cooldown > 0)
return FALSE
cooldown = 2
- spawn(10)
- process_cooldown()
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
signal()
return TRUE
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index cab132ab747..5bbd9a26538 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -39,12 +39,11 @@
/obj/item/assembly/timer/proc/timer_end()
if(!secured || cooldown > 0)
return FALSE
- pulse(0)
+ cooldown = 2
+ pulse(FALSE)
if(loc)
loc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
- cooldown = 2
- spawn(10)
- process_cooldown()
+ addtimer(CALLBACK(src, .proc/process_cooldown), 10)
/obj/item/assembly/timer/process()
if(timing && (time > 0))
diff --git a/code/modules/atmos_automation/console.dm b/code/modules/atmos_automation/console.dm
deleted file mode 100644
index 8d23bb390aa..00000000000
--- a/code/modules/atmos_automation/console.dm
+++ /dev/null
@@ -1,454 +0,0 @@
-/obj/machinery/computer/general_air_control/atmos_automation
- icon = 'icons/obj/computer.dmi'
- icon_screen = "area_atmos"
- icon_keyboard = "atmos_key"
- circuit = /obj/item/circuitboard/atmos_automation
- req_one_access_txt = "24;10"
- Mtoollink = 1
-
- show_sensors = 0
- var/on = 0
-
- name = "Atmospherics Automations Console"
-
- var/list/datum/automation/automations = list()
-
-/obj/machinery/computer/general_air_control/atmos_automation/receive_signal(datum/signal/signal)
- if(!signal || signal.encryption) return
-
- var/id_tag = signal.data["tag"]
- if(!id_tag)
- return
-
- sensor_information[id_tag] = signal.data
-
-/obj/machinery/computer/general_air_control/atmos_automation/process()
- if(on)
- for(var/datum/automation/A in automations)
- A.process()
-
-/obj/machinery/computer/general_air_control/atmos_automation/update_icon()
- icon_state = initial(icon_state)
- // Broken
- if(stat & BROKEN)
- icon_state += "b"
-
- // Powered
- else if(stat & NOPOWER)
- icon_state = initial(icon_state)
- icon_state += "0"
- else if(on)
- icon_state += "_active"
-
-/obj/machinery/computer/general_air_control/atmos_automation/proc/request_device_refresh(device)
- send_signal(list("tag"=device, "status"))
-
-/obj/machinery/computer/general_air_control/atmos_automation/proc/send_signal(list/data, filter = RADIO_ATMOSIA)//filter's here so the AAC can cross communicate to things like vents, which have a different filter
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- signal.data=data
- signal.data["sigtype"]="command"
- signal.data["advcontrol"]=1//AAC balancing, you need to manually get up to the machine to make it listen to this
- radio_connection.post_signal(src, signal, range = 8, filter = filter)
-
-/obj/machinery/computer/general_air_control/atmos_automation/proc/selectValidChildFor(datum/automation/parent, mob/user, list/valid_returntypes)
- var/list/choices=list()
- for(var/childtype in GLOB.automation_types)
- var/datum/automation/A = new childtype(src)
- if(A.returntype == null)
- continue
- if(!(A.returntype in valid_returntypes))
- continue
- choices[A.name]=A
- if(choices.len==0)
- testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!")
- return 0
- var/label=input(user, "Select new automation:", "Automations", "Cancel") as null|anything in choices
- if(!label)
- return 0
- return choices[label]
-
-/obj/machinery/computer/general_air_control/atmos_automation/return_text()
- var/out=..()
-
- if(on)
- out += "RUNNING"
- else
- out += "STOPPED"
-
- out += {"
-
"
- return out
-
- Topic(href,href_list)
- if(href_list["add"])
- var/new_child=selectValidChildFor(usr)
- if(!new_child) return 1
- switch(href_list["add"])
- if("then")
- children_then += new_child
- if("else")
- children_else += new_child
- else
- warning("Unknown add value given to [type]/Topic():[__LINE__]: [href]")
- return 1
- parent.updateUsrDialog()
- return 1
- if(href_list["remove"])
- if(href_list["remove"]=="*")
- var/confirm=input("Are you sure you want to remove ALL automations?","Automations","No") in list("Yes","No")
- if(confirm == "No") return 0
- for(var/datum/automation/A in children_then)
- A.OnRemove()
- children_then.Remove(A)
- for(var/datum/automation/A in children_else)
- A.OnRemove()
- children_else.Remove(A)
- else
- var/datum/automation/A=locate(href_list["remove"])
- if(!A) return 1
- var/confirm=input("Are you sure you want to remove this automation?","Automations","No") in list("Yes","No")
- if(confirm == "No") return 0
- A.OnRemove()
- switch(href_list["context"])
- if("then")
- children_then.Remove(A)
- if("else")
- children_else.Remove(A)
- parent.updateUsrDialog()
- return 1
- if(href_list["reset"])
- if(href_list["reset"]=="*")
- for(var/datum/automation/A in children_then)
- A.OnReset()
- for(var/datum/automation/A in children_else)
- A.OnReset()
- else
- var/datum/automation/A=locate(href_list["reset"])
- if(!A) return 1
- A.OnReset()
- parent.updateUsrDialog()
- return 1
- if(href_list["set_condition"])
- var/new_condition = selectValidChildFor(usr,valid_conditions)
- testing("Selected condition: [new_condition]")
- if(!new_condition)
- return 1
- condition = new_condition
- parent.updateUsrDialog()
- return 1
-
- process()
- if(condition)
- if(condition.Evaluate())
- for(var/datum/automation/stmt in children_then)
- stmt.process()
- else
- for(var/datum/automation/stmt in children_else)
- stmt.process()
-
-///////////////////////////////////////////
-// compare
-///////////////////////////////////////////
-
-/datum/automation/compare
- name = "comparison"
- var/comparator="Greater Than"
- returntype=AUTOM_RT_NUM
- valid_child_returntypes=list(AUTOM_RT_NUM)
-
- New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
- ..(aa)
- children=list(null,null)
-
- Export()
- var/list/json = ..()
- json["cmp"]=comparator
- return json
-
- Import(var/list/json)
- ..(json)
- comparator = json["cmp"]
-
- Evaluate()
- if(children.len<2)
- return 0
- var/datum/automation/d_left =children[1]
- var/datum/automation/d_right=children[2]
- if(!d_left || !d_right)
- return 0
- var/left=d_left.Evaluate()
- var/right=d_right.Evaluate()
- switch(comparator)
- if("Greater Than")
- return left>right
- if("Greater Than or Equal to")
- return left>=right
- if("Less Than")
- return left(Set Left) ("
- if(left==null)
- out += "-----"
- else
- out += left.GetText()
-
- out += ") is [comparator]: (Set Right) ("
-
- if(right==null)
- out += "-----"
- else
- out += right.GetText()
- out +=")"
- return out
-
- Topic(href,href_list)
- if(href_list["set_comparator"])
- comparator = input("Select a comparison operator:", "Compare", "Greater Than") in list("Greater Than","Greater Than or Equal to","Less Than","Less Than or Equal to","Equal to","NOT Equal To")
- parent.updateUsrDialog()
- return 1
- if(href_list["set_field"])
- var/idx = text2num(href_list["set_field"])
- var/new_child = selectValidChildFor(usr)
- if(!new_child)
- return 1
- children[idx] = new_child
- parent.updateUsrDialog()
- return 1
-
-///////////////////////////////////////////
-// static value
-///////////////////////////////////////////
-
-/datum/automation/static_value
- name = "Number"
-
- var/value=0
-
- returntype=AUTOM_RT_NUM
-
- Evaluate()
- return value
-
- Export()
- var/list/json = ..()
- json["value"]=value
- return json
-
- Import(var/list/json)
- ..(json)
- value = text2num(json["value"])
-
- GetText()
- return "[value]"
-
- Topic(href,href_list)
- if(href_list["set_value"])
- value = input("Set a value:", "Static Value", value) as num
- parent.updateUsrDialog()
- return 1
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 1086f43dd48..bac8d64d9f2 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -163,11 +163,11 @@
var/pda = -1
var/backpack_contents = -1
var/suit_store = -1
-
var/hair_style
var/facial_hair_style
var/skin_tone
+ var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
/obj/effect/mob_spawn/human/Initialize()
if(ispath(outfit))
@@ -227,7 +227,6 @@
if(!isnum(T))
outfit.vars[slot] = T
H.equipOutfit(outfit)
- var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
for(var/del_type in del_types)
var/obj/item/I = locate(del_type) in H
qdel(I)
diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm
index fc268c3ba35..0118b0febb4 100644
--- a/code/modules/awaymissions/gateway.dm
+++ b/code/modules/awaymissions/gateway.dm
@@ -1,4 +1,4 @@
-var/obj/machinery/gateway/centerstation/the_gateway = null
+GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
@@ -41,21 +41,21 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centerstation/New()
..()
- if(!the_gateway)
- the_gateway = src
+ if(!GLOB.the_gateway)
+ GLOB.the_gateway = src
/obj/machinery/gateway/centerstation/Initialize()
..()
update_icon()
wait = world.time + config.gateway_delay //+ thirty minutes default
- awaygate = locate(/obj/machinery/gateway/centeraway) in world
+ awaygate = locate(/obj/machinery/gateway/centeraway) in GLOB.machines
/obj/machinery/gateway/centerstation/update_density_from_dir()
return
/obj/machinery/gateway/centerstation/Destroy()
- if(the_gateway == src)
- the_gateway = null
+ if(GLOB.the_gateway == src)
+ GLOB.the_gateway = null
return ..()
/obj/machinery/gateway/centerstation/update_icon()
@@ -103,7 +103,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
if(!powered())
return
if(!awaygate)
- awaygate = locate(/obj/machinery/gateway/centeraway) in world
+ awaygate = locate(/obj/machinery/gateway/centeraway) in GLOB.machines
if(!awaygate)
to_chat(user, "Error: No destination found.")
return
@@ -180,7 +180,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centeraway/Initialize()
..()
update_icon()
- stationgate = locate(/obj/machinery/gateway/centerstation) in world
+ stationgate = locate(/obj/machinery/gateway/centerstation) in GLOB.machines
/obj/machinery/gateway/centeraway/update_density_from_dir()
@@ -219,7 +219,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
if(linked.len != 8)
return
if(!stationgate)
- stationgate = locate(/obj/machinery/gateway/centerstation) in world
+ stationgate = locate(/obj/machinery/gateway/centerstation) in GLOB.machines
if(!stationgate)
to_chat(user, "Error: No destination found.")
return
diff --git a/code/modules/awaymissions/maploader/dmm_suite.dm b/code/modules/awaymissions/maploader/dmm_suite.dm
index 1eee3d8fc34..5e958f28ee6 100644
--- a/code/modules/awaymissions/maploader/dmm_suite.dm
+++ b/code/modules/awaymissions/maploader/dmm_suite.dm
@@ -1,72 +1,82 @@
-GLOBAL_DATUM_INIT(maploader, /dmm_suite, new())
-dmm_suite{
- /*
+/*
- dmm_suite version 1.0
- Released January 30th, 2011.
+ dmm_suite version 1.0
+ Released January 30th, 2011.
- defines the object /dmm_suite
- - Provides the proc load_map()
- - Loads the specified map file onto the specified z-level.
- - provides the proc write_map()
- - Returns a text string of the map in dmm format
- ready for output to a file.
- - provides the proc save_map()
- - Returns a .dmm file if map is saved
- - Returns FALSE if map fails to save
+ defines the object /dmm_suite
+ - Provides the proc load_map()
+ - Loads the specified map file onto the specified z-level.
+ - provides the proc write_map()
+ - Returns a text string of the map in dmm format
+ ready for output to a file.
+ - provides the proc save_map()
+ - Returns a .dmm file if map is saved
+ - Returns FALSE if map fails to save
- The dmm_suite provides saving and loading of map files in BYOND's native DMM map
- format. It approximates the map saving and loading processes of the Dream Maker
- and Dream Seeker programs so as to allow editing, saving, and loading of maps at
- runtime.
+ The dmm_suite provides saving and loading of map files in BYOND's native DMM map
+ format. It approximates the map saving and loading processes of the Dream Maker
+ and Dream Seeker programs so as to allow editing, saving, and loading of maps at
+ runtime.
- ------------------------
+ ------------------------
- To save a map at runtime, create an instance of /dmm_suite, and then call
- write_map(), which accepts three arguments:
- - A turf representing one corner of a three dimensional grid (Required).
- - Another turf representing the other corner of the same grid (Required).
- - Any, or a combination, of several bit flags (Optional, see documentation).
+ To save a map at runtime, create an instance of /dmm_suite, and then call
+ write_map(), which accepts three arguments:
+ - A turf representing one corner of a three dimensional grid (Required).
+ - Another turf representing the other corner of the same grid (Required).
+ - Any, or a combination, of several bit flags (Optional, see documentation).
- The order in which the turfs are supplied does not matter, the /dmm_writer will
- determine the grid containing both, in much the same way as DM's block() function.
- write_map() will then return a string representing the saved map in dmm format;
- this string can then be saved to a file, or used for any other purose.
+ The order in which the turfs are supplied does not matter, the /dmm_writer will
+ determine the grid containing both, in much the same way as DM's block() function.
+ write_map() will then return a string representing the saved map in dmm format;
+ this string can then be saved to a file, or used for any other purose.
- ------------------------
+ ------------------------
- To load a map at runtime, create an instance of /dmm_suite, and then call load_map(),
- which accepts two arguments:
- - A .dmm file to load (Required).
- - A number representing the z-level on which to start loading the map (Optional).
+ To load a map at runtime, create an instance of /dmm_suite, and then call load_map(),
+ which accepts two arguments:
+ - A .dmm file to load (Required).
+ - A number representing the z-level on which to start loading the map (Optional).
- The /dmm_suite will load the map file starting on the specified z-level. If no
- z-level was specified, world.maxz will be increased so as to fit the map. Note
- that if you wish to load a map onto a z-level that already has objects on it,
- you will have to handle the removal of those objects. Otherwise the new map will
- simply load the new objects on top of the old ones.
+ The /dmm_suite will load the map file starting on the specified z-level. If no
+ z-level was specified, world.maxz will be increased so as to fit the map. Note
+ that if you wish to load a map onto a z-level that already has objects on it,
+ you will have to handle the removal of those objects. Otherwise the new map will
+ simply load the new objects on top of the old ones.
- Also note that all type paths specified in the .dmm file must exist in the world's
- code, and that the /dmm_reader trusts that files to be loaded are in fact valid
- .dmm files. Errors in the .dmm format will cause runtime errors.
+ Also note that all type paths specified in the .dmm file must exist in the world's
+ code, and that the /dmm_reader trusts that files to be loaded are in fact valid
+ .dmm files. Errors in the .dmm format will cause runtime errors.
- */
+*/
- verb/load_map(var/dmm_file as file, var/x_offset as num, var/y_offset as num, var/z_offset as num, do_sleep as num){
- // dmm_file: A .dmm file to load (Required).
- // z_offset: A number representing the z-level on which to start loading the map (Optional).
- }
- verb/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){
- // t1: A turf representing one corner of a three dimensional grid (Required).
- // t2: Another turf representing the other corner of the same grid (Required).
- // flags: Any, or a combination, of several bit flags (Optional, see documentation).
- }
+GLOBAL_DATUM_INIT(maploader, /datum/dmm_suite, new())
- // save_map is included as a legacy proc. Use write_map instead.
- verb/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){
- // t1: A turf representing one corner of a three dimensional grid (Required).
- // t2: Another turf representing the other corner of the same grid (Required).
- // map_name: A valid name for the map to be saved, such as "castle" (Required).
- // flags: Any, or a combination, of several bit flags (Optional, see documentation).
- }
- }
+/datum/dmm_suite
+ var/static/quote = "\""
+
+ // These regexes are global - meaning that starting the maploader again mid-load will
+ // reset progress - which means we need to track our index per-map, or we'll
+ // eternally recurse
+ // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
+ var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
+ // /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
+ var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
+ // /^[\s\n]+|[\s\n]+$/
+ var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
+ var/static/list/modelCache = list()
+
+ var/static/list/letter_digits = list(
+ "a", "b", "c", "d", "e",
+ "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o",
+ "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y",
+ "z",
+ "A", "B", "C", "D", "E",
+ "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O",
+ "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y",
+ "Z"
+ )
diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm
index 9a7cf6b6405..f034c4f39d1 100644
--- a/code/modules/awaymissions/maploader/reader.dm
+++ b/code/modules/awaymissions/maploader/reader.dm
@@ -1,23 +1,11 @@
///////////////////////////////////////////////////////////////
-//SS13 Optimized Map loader
+// SS13 Optimized Map loader
//////////////////////////////////////////////////////////////
-//As of 3.6.2016
-//global datum that will preload variables on atoms instanciation
+// As of 3.6.2016
+// global datum that will preload variables on atoms instanciation
GLOBAL_VAR_INIT(use_preloader, FALSE)
-GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
-
-/dmm_suite
- // These regexes are global - meaning that starting the maploader again mid-load will
- // reset progress - which means we need to track our index per-map, or we'll
- // eternally recurse
- // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
- var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
- // /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
- var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
- // /^[\s\n]+|[\s\n]+$/
- var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
- var/static/list/modelCache = list()
+GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
/**
* Construct the model map and control the loading process
@@ -37,13 +25,18 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
* atmos will attempt to start before it's ready, causing runtimes galore if init is
* allowed to romp unchecked.
*/
-/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num)
- var/tfile = dmm_file//the map file we're creating
+/datum/dmm_suite/proc/load_map(dmm_file, x_offset = 0, y_offset = 0, z_offset = 0, shouldCropMap = FALSE, measureOnly = FALSE)
+ var/tfile = dmm_file// the map file we're creating
var/fname = "Lambda"
if(isfile(tfile))
fname = "[tfile]"
+ // Make sure we dont load a dir up
+ var/lastchar = copytext(fname, -1)
+ if(lastchar == "/" || lastchar == "\\")
+ log_debug("Attempted to load map template without filename (Attempted [tfile])")
+ return
tfile = file2text(tfile)
- if(length(tfile) == 0)
+ if(!length(tfile))
throw EXCEPTION("Map path '[fname]' does not exist!")
if(!x_offset)
@@ -57,7 +50,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
var/list/grid_models = list()
var/key_len = 0
- var/dmm_suite/loaded_map/LM = new
+ var/datum/dmm_suite/loaded_map/LM = new
// This try-catch is used as a budget "Finally" clause, as the dirt count
// needs to be reset
var/watch = start_watch()
@@ -76,7 +69,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
if(!key_len)
key_len = length(key)
else
- throw EXCEPTION("Inconsistant key length in DMM")
+ throw EXCEPTION("Inconsistent key length in DMM")
if(!measureOnly)
grid_models[key] = dmmRegex.group[2]
@@ -86,17 +79,17 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
throw EXCEPTION("Coords before model definition in DMM")
var/xcrdStart = text2num(dmmRegex.group[3]) + x_offset - 1
- //position of the currently processed square
+ // position of the currently processed square
var/xcrd
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
if(!measureOnly)
if(zcrd > world.maxz)
- if(cropMap)
+ if(shouldCropMap)
continue
else
- GLOB.space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed
+ GLOB.space_manager.increase_max_zlevel_to(zcrd) // create a new z_level if needed
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
@@ -118,7 +111,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
bounds[MAP_MINY] = min(bounds[MAP_MINY], ycrd)
ycrd += gridLines.len - 1 // Start at the top and work down
- if(!cropMap && ycrd > world.maxy)
+ if(!shouldCropMap && ycrd > world.maxy)
if(!measureOnly)
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], ycrd)
@@ -133,9 +126,9 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
for(var/line in gridLines)
if(ycrd <= world.maxy && ycrd >= 1)
xcrd = xcrdStart
- for(var/tpos = 1 to length(line) - key_len + 1 step key_len)
+ for(var/tpos = 1 to (length(line) - key_len + 1) step key_len)
if(xcrd > world.maxx)
- if(cropMap)
+ if(shouldCropMap)
break
else
world.maxx = xcrd
@@ -152,7 +145,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
maxx = max(maxx, xcrd)
++xcrd
--ycrd
- bounds[MAP_MAXX] = max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx)
+ bounds[MAP_MAXX] = max(bounds[MAP_MAXX], shouldCropMap ? min(maxx, world.maxx) : maxx)
CHECK_TICK
catch(var/exception/e)
@@ -175,8 +168,8 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
if(!measureOnly)
for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
var/turf/T = t
- //we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
- T.AfterChange(1, keep_cabling = TRUE)
+ // we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
+ T.AfterChange(TRUE, keep_cabling = TRUE)
return bounds
/**
@@ -196,14 +189,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
* 4) Instanciates the atom with its variables
*
*/
-/dmm_suite/proc/parse_grid(model as text,xcrd as num,ycrd as num,zcrd as num, dmm_suite/loaded_map/LM)
+/datum/dmm_suite/proc/parse_grid(model = "", xcrd = 0, ycrd = 0, zcrd = 0, datum/dmm_suite/loaded_map/LM)
/*Method parse_grid()
- Accepts a text string containing a comma separated list of type paths of the
same construction as those contained in a .dmm file, and instantiates them.
*/
- var/list/members //will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
- var/list/members_attributes //will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
+ var/list/members // will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
+ var/list/members_attributes // will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
var/list/cached = modelCache[model]
var/index
@@ -212,7 +205,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
members_attributes = cached[2]
else
/////////////////////////////////////////////////////////
- //Constructing members and corresponding variables lists
+ // Constructing members and corresponding variables lists
////////////////////////////////////////////////////////
members = list()
@@ -223,13 +216,13 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
var/dpos
do
- //finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
- dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
+ // finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
+ dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") // find next delimiter (comma here) that's not within {...}
- var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
+ var/full_def = trim_text(copytext(model, old_position, dpos)) // full definition, e.g : /obj/foo/bar{variables=derp}
var/variables_start = findtext(full_def, "{")
var/atom_text = trim_text(copytext(full_def, 1, variables_start))
- var/atom_def = text2path(atom_text) //path definition, e.g /obj/foo/bar
+ var/atom_def = text2path(atom_text) // path definition, e.g /obj/foo/bar
old_position = dpos + 1
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
@@ -237,14 +230,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
continue
members.Add(atom_def)
- //transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
+ // transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
var/list/fields = list()
- if(variables_start)//if there's any variable
- full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
+ if(variables_start) // if there's any variable
+ full_def = copytext(full_def, variables_start + 1, length(full_def)) // removing the last '}'
fields = readlist(full_def, ";")
- //then fill the members_attributes list with the corresponding variables
+ // then fill the members_attributes list with the corresponding variables
members_attributes.len++
members_attributes[index++] = fields
@@ -255,24 +248,23 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
////////////////
- //Instanciation
+ // Instanciation
////////////////
- //The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
+ // The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
- //first instance the /area and remove it from the members list
+ // first instance the /area and remove it from the members list
index = members.len
- var/turf/crds = locate(xcrd,ycrd,zcrd)
+ var/turf/crds = locate(xcrd, ycrd, zcrd)
if(members[index] != /area/template_noop)
// We assume `members[index]` is an area path, as above, yes? I will operate
// on that assumption.
if(!ispath(members[index], /area))
throw EXCEPTION("Oh no, I thought this was an area!")
- var/atom/instance
- GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
- instance = LM.area_path_to_real_area(members[index])
+ GLOB._preloader.setup(members_attributes[index]) // preloader for assigning set variables on atom creation
+ var/atom/instance = LM.area_path_to_real_area(members[index])
if(crds)
instance.contents.Add(crds)
@@ -280,45 +272,46 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
if(GLOB.use_preloader && instance)
GLOB._preloader.load(instance)
- //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
+ // then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
var/first_turf_index = 1
- while(!ispath(members[first_turf_index],/turf)) //find first /turf object in members
+ while(!ispath(members[first_turf_index], /turf)) // find first /turf object in members
first_turf_index++
- //instanciate the first /turf
+ // instanciate the first /turf
var/turf/T
if(members[first_turf_index] != /turf/template_noop)
- T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],xcrd,ycrd,zcrd)
+ T = instance_atom(members[first_turf_index], members_attributes[first_turf_index], xcrd, ycrd, zcrd)
if(T)
- //if others /turf are presents, simulates the underlays piling effect
+ // if others /turf are presents, simulates the underlays piling effect
index = first_turf_index + 1
- while(index <= members.len - 1) // Last item is an /area
+ var/mlen = members.len - 1
+ while(index <= mlen) // Last item is an /area
var/underlay
if(istype(T, /turf)) // I blame this on the stupid clown who coded the BYOND map editor
underlay = T.appearance
- T = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
- if(ispath(members[index],/turf))
+ T = instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd) // instance new turf
+ if(ispath(members[index], /turf))
T.underlays += underlay
index++
- //finally instance all remainings objects/mobs
- for(index in 1 to first_turf_index-1)
- instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)
+ // finally instance all remainings objects/mobs
+ for(index in 1 to first_turf_index - 1)
+ instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd)
CHECK_TICK
////////////////
-//Helpers procs
+// Helpers procs
////////////////
-//Instance an atom at (x,y,z) and gives it the variables in attributes
-/dmm_suite/proc/instance_atom(path,list/attributes, x, y, z)
+// Instance an atom at (x, y, z) and gives it the variables in attributes
+/datum/dmm_suite/proc/instance_atom(path, list/attributes, x, y, z)
var/atom/instance
GLOB._preloader.setup(attributes, path)
- var/turf/T = locate(x,y,z)
+ var/turf/T = locate(x, y, z)
if(T)
if(ispath(path, /turf))
T.ChangeTurf(path, defer_change = TRUE, keep_icon = FALSE)
@@ -326,115 +319,111 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
else if(ispath(path, /area))
else
- instance = new path (T)//first preloader pass
+ instance = new path(T) // first preloader pass
- if(GLOB.use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
+ if(GLOB.use_preloader && instance) // second preloader pass, for those atoms that don't ..() in New()
GLOB._preloader.load(instance)
return instance
-//text trimming (both directions) helper proc
-//optionally removes quotes before and after the text (for variable name)
-/dmm_suite/proc/trim_text(what as text,trim_quotes=0)
+// text trimming (both directions) helper proc
+// optionally removes quotes before and after the text (for variable name)
+/datum/dmm_suite/proc/trim_text(what, trim_quotes = FALSE)
if(trim_quotes)
return trimQuotesRegex.Replace(what, "")
else
return trimRegex.Replace(what, "")
-
-//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
-//returns 0 if reached the last delimiter
-/dmm_suite/proc/find_next_delimiter_position(text as text,initial_position as num, delimiter=",",opening_escape=quote,closing_escape=quote)
+// find the position of the next delimiter, skipping whatever is comprised between opening_escape and closing_escape
+// returns 0 if reached the last delimiter
+/datum/dmm_suite/proc/find_next_delimiter_position(text, initial_position = 0, delimiter = ",", opening_escape = quote, closing_escape = quote)
var/position = initial_position
- var/next_delimiter = findtext(text,delimiter,position,0)
- var/next_opening = findtext(text,opening_escape,position,0)
+ var/next_delimiter = findtext(text, delimiter, position, 0)
+ var/next_opening = findtext(text, opening_escape, position, 0)
while((next_opening != 0) && (next_opening < next_delimiter))
- position = findtext(text,closing_escape,next_opening + 1,0)+1
- next_delimiter = findtext(text,delimiter,position,0)
- next_opening = findtext(text,opening_escape,position,0)
+ position = findtext(text, closing_escape, next_opening + 1, 0) + 1
+ next_delimiter = findtext(text, delimiter, position, 0)
+ next_opening = findtext(text, opening_escape, position, 0)
return next_delimiter
-
-//build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
-//return the filled list
-/dmm_suite/proc/readlist(text as text, delimiter=",")
-
+// build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
+// return the filled list
+/datum/dmm_suite/proc/readlist(text, delimiter = ",")
var/list/to_return = list()
var/position
var/old_position = 1
do
- //find next delimiter that is not within "..."
- position = find_next_delimiter_position(text,old_position,delimiter)
+ // find next delimiter that is not within "..."
+ position = find_next_delimiter_position(text, old_position, delimiter)
- //check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7))
- var/equal_position = findtext(text,"=",old_position, position)
+ // check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo", var2=7))
+ var/equal_position = findtext(text, "=", old_position, position)
- var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position)),1)//the name of the variable, must trim quotes to build a BYOND compliant associatives list
+ var/trim_left = trim_text(copytext(text, old_position, (equal_position ? equal_position : position)), 1) // the name of the variable, must trim quotes to build a BYOND compliant associatives list
old_position = position + 1
- if(equal_position)//associative var, so do the association
- var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable
+ if(equal_position) // associative var, so do the association
+ var/trim_right = trim_text(copytext(text, equal_position + 1, position)) // the content of the variable
- //Check for string
+ // Check for string
// Make it read to the next delimiter, instead of the quote
- if(findtext(trim_right,quote,1,2))
- var/endquote = findtext(trim_right,quote,-1)
+ if(findtext(trim_right, quote, 1, 2))
+ var/endquote = findtext(trim_right, quote, -1)
if(!endquote)
log_runtime(EXCEPTION("Terminating quote not found!"), src)
// Our map writer escapes quotes and curly brackets to avoid
// letting our simple parser choke on meanly-crafted names/etc
// - so we decode it here so it's back to good ol' legibility
- trim_right = dmm_decode(copytext(trim_right,2,endquote))
+ trim_right = dmm_decode(copytext(trim_right, 2, endquote))
- //Check for number
+ // Check for number
else if(isnum(text2num(trim_right)))
trim_right = text2num(trim_right)
- //Check for null
+ // Check for null
else if(trim_right == "null")
trim_right = null
- //Check for list
- else if(copytext(trim_right,1,5) == "list")
- trim_right = readlist(copytext(trim_right,6,length(trim_right)))
+ // Check for list
+ else if(copytext(trim_right, 1, 5) == "list")
+ trim_right = readlist(copytext(trim_right, 6, length(trim_right)))
- //Check for file
- else if(copytext(trim_right,1,2) == "'")
- trim_right = file(copytext(trim_right,2,length(trim_right)))
+ // Check for file
+ else if(copytext(trim_right, 1, 2) == "'")
+ trim_right = file(copytext(trim_right, 2, length(trim_right)))
- //Check for path
+ // Check for path
else if(ispath(text2path(trim_right)))
trim_right = text2path(trim_right)
to_return[trim_left] = trim_right
- else//simple var
+ else// simple var
to_return[trim_left] = null
while(position != 0)
return to_return
-/dmm_suite/Destroy()
+/datum/dmm_suite/Destroy()
..()
return QDEL_HINT_HARDDEL_NOW
//////////////////
-//Preloader datum
+// Preloader datum
//////////////////
// This ain't re-entrant, but we had this before the maploader update
-/dmm_suite/preloader
- parent_type = /datum
+/datum/dmm_suite/preloader
var/list/attributes
var/target_path
var/json_ready = 0
-/dmm_suite/preloader/proc/setup(list/the_attributes, path)
+/datum/dmm_suite/preloader/proc/setup(list/the_attributes, path)
if(the_attributes.len)
json_ready = 0
if("map_json_data" in the_attributes)
@@ -443,25 +432,24 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
attributes = the_attributes
target_path = path
-/dmm_suite/preloader/proc/load(atom/what)
+/datum/dmm_suite/preloader/proc/load(atom/A)
if(json_ready)
- var/json_data = attributes["map_json_data"]
+ var/json_data = dmm_decode(attributes["map_json_data"])
attributes -= "map_json_data"
- json_data = dmm_decode(json_data)
try
- what.deserialize(json_decode(json_data))
- catch(var/exception/e)
+ A.deserialize(json_decode(json_data))
+ catch(var/exception/E)
log_runtime(EXCEPTION("Bad json data: '[json_data]'"), src)
- throw e
+ throw E
for(var/attribute in attributes)
var/value = attributes[attribute]
if(islist(value))
value = deepCopyList(value)
- what.vars[attribute] = value
+ A.vars[attribute] = value
GLOB.use_preloader = FALSE
// If the map loader fails, make this safe
-/dmm_suite/preloader/proc/reset()
+/datum/dmm_suite/preloader/proc/reset()
GLOB.use_preloader = FALSE
attributes = list()
target_path = null
@@ -470,12 +458,11 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
// so that one can have separate "unpowered" areas for ruins or whatever,
// yet have a single area type for use of mapping, instead of creating
// a new area type for each new ruin
-/dmm_suite/loaded_map
- parent_type = /datum
+/datum/dmm_suite/loaded_map
var/list/area_list = list()
var/index = 1 // To store the state of the regex
-/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
+/datum/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
if(!ispath(A, /area))
throw EXCEPTION("Wrong argument to `area_path_to_real_area`")
diff --git a/code/modules/awaymissions/maploader/writer.dm b/code/modules/awaymissions/maploader/writer.dm
index c6d1fd589cf..b609f26c69d 100644
--- a/code/modules/awaymissions/maploader/writer.dm
+++ b/code/modules/awaymissions/maploader/writer.dm
@@ -5,28 +5,12 @@
#define DMM_IGNORE_PLAYERS 16
#define DMM_IGNORE_MOBS 24
#define DMM_USE_JSON 32
-/dmm_suite
- var/quote = "\""
- var/list/letter_digits = list(
- "a","b","c","d","e",
- "f","g","h","i","j",
- "k","l","m","n","o",
- "p","q","r","s","t",
- "u","v","w","x","y",
- "z",
- "A","B","C","D","E",
- "F","G","H","I","J",
- "K","L","M","N","O",
- "P","Q","R","S","T",
- "U","V","W","X","Y",
- "Z"
- )
-/dmm_suite/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num)
- //Check for illegal characters in file name... in a cheap way.
- if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name)))
+/datum/dmm_suite/proc/save_map(turf/t1, turf/t2, map_name = "", flags = 0)
+ // Check for illegal characters in file name... in a cheap way.
+ if(!((ckeyEx(map_name) == map_name) && ckeyEx(map_name)))
CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.")
- //Check for valid turfs.
+ // Check for valid turfs.
if(!isturf(t1) || !isturf(t2))
CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.")
@@ -35,17 +19,17 @@
if(fexists(map_path))
fdel(map_path)
var/saved_map = file(map_path)
- var/map_text = write_map(t1,t2,flags,saved_map)
+ var/map_text = write_map(t1, t2, flags, saved_map)
saved_map << map_text
return saved_map
-/dmm_suite/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num)
- //Check for valid turfs.
+/datum/dmm_suite/proc/write_map(turf/t1, turf/t2, flags = 0)
+ // Check for valid turfs.
if(!isturf(t1) || !isturf(t2))
CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.")
- var/turf/ne = locate(max(t1.x,t2.x),max(t1.y,t2.y),max(t1.z,t2.z)) // Outer corner
- var/turf/sw = locate(min(t1.x,t2.x),min(t1.y,t2.y),min(t1.z,t2.z)) // Inner corner
+ var/turf/ne = locate(max(t1.x, t2.x), max(t1.y, t2.y), max(t1.z, t2.z)) // Outer corner
+ var/turf/sw = locate(min(t1.x, t2.x), min(t1.y, t2.y), min(t1.z, t2.z)) // Inner corner
var/list/templates[0]
var/list/template_buffer = list()
var/template_buffer_text
@@ -54,37 +38,40 @@
var/total_timer = start_watch()
var/timer = start_watch()
log_debug("Reading turfs...")
+
// Read the contents of all the turfs we were given
for(var/pos_z in sw.z to ne.z)
for(var/pos_y in ne.y to sw.y step -1) // We're reversing this because the map format is silly
for(var/pos_x in sw.x to ne.x)
- var/turf/test_turf = locate(pos_x,pos_y,pos_z)
+ var/turf/test_turf = locate(pos_x, pos_y, pos_z)
var/test_template = make_template(test_turf, flags)
var/template_number = templates.Find(test_template)
if(!template_number)
templates.Add(test_template)
- template_number = templates.len
+ template_number = length(templates)
template_buffer += "[template_number],"
CHECK_TICK
-
template_buffer += ";"
-
template_buffer += "."
- template_buffer_text = jointext(template_buffer,"")
+
+ template_buffer_text = jointext(template_buffer, "")
log_debug("Reading turfs took [stop_watch(timer)]s.")
- if(templates.len == 0)
+ if(length(templates) == 0)
CRASH("No templates found!")
- var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1)
- var/list/keys[templates.len]
+
+ var/key_length = round(log(length(letter_digits), length(templates) - 1) + 1) // or floor
+ var/list/keys[length(templates)]
+
// Write the list of key/model pairs to the file
timer = start_watch()
log_debug("Writing out key/model pairs to file header...")
var/list/key_models = list()
- for(var/key_pos in 1 to templates.len)
- keys[key_pos] = get_model_key(key_pos,key_length)
+ for(var/key_pos in 1 to length(templates))
+ keys[key_pos] = get_model_key(key_pos, key_length)
key_models += "\"[keys[key_pos]]\" = ([templates[key_pos]])\n"
CHECK_TICK
+
dmm_text += jointext(key_models,"")
log_debug("Writing key/model pairs complete, took [stop_watch(timer)]s.")
@@ -92,58 +79,69 @@
// Loop over all z in our zone
timer = start_watch()
log_debug("Writing out key map...")
+
var/list/key_map = list()
- for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer_text,".",z_pos)+1)
- if(z_pos>=length(template_buffer_text)) break
- if(z_level) key_map += "\n"
+ for(var/z_pos = 1; TRUE; z_pos = findtext(template_buffer_text, ".", z_pos) + 1)
+ if(z_pos >= length(template_buffer_text))
+ break
+
+ if(z_level)
+ key_map += "\n"
+
key_map += "\n(1,1,[++z_level]) = {\"\n"
- var/z_block = copytext(template_buffer_text,z_pos,findtext(template_buffer_text,".",z_pos))
- for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1)
- if(y_pos>=length(z_block)) break
- var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos))
+ var/z_block = copytext(template_buffer_text, z_pos, findtext(template_buffer_text, ".", z_pos))
+ for(var/y_pos = 1; TRUE; y_pos = findtext(z_block, ";", y_pos) + 1)
+ if(y_pos >= length(z_block))
+ break
+
+ var/y_block = copytext(z_block, y_pos, findtext(z_block, ";", y_pos))
// A row of keys
- for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1)
- if(x_pos>=length(y_block)) break
- var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos))
+ for(var/x_pos = 1; TRUE; x_pos = findtext(y_block, ",", x_pos) + 1)
+ if(x_pos >= length(y_block))
+ break
+
+ var/x_block = copytext(y_block, x_pos, findtext(y_block, ",", x_pos))
var/key_number = text2num(x_block)
var/temp_key = keys[key_number]
key_map += temp_key
CHECK_TICK
key_map += "\n"
key_map += "\"}"
- dmm_text += jointext(key_map,"")
+
+ dmm_text += jointext(key_map, "")
log_debug("Writing key map complete, took [stop_watch(timer)]s.")
log_debug("TOTAL TIME: [stop_watch(total_timer)]s.")
+
return dmm_text
-/dmm_suite/proc/make_template(var/turf/model as turf, var/flags as num)
- var/use_json = 0
- if(flags & DMM_USE_JSON)
- use_json = 1
+/datum/dmm_suite/proc/make_template(turf/model, flags = 0)
+ var/use_json = (flags & DMM_USE_JSON) ? TRUE : FALSE
+
var/template = ""
var/turf_template = ""
var/list/obj_template = list()
var/list/mob_template = list()
var/area_template = ""
-
-
// Turf
if(!(flags & DMM_IGNORE_TURFS))
turf_template = "[model.type][check_attributes(model,use_json=use_json)],"
- else turf_template = "[world.turf],"
+ else
+ turf_template = "[world.turf],"
// Objects loop
if(!(flags & DMM_IGNORE_OBJS))
for(var/obj/O in model.contents)
if(O.dont_save || QDELETED(O))
continue
+
obj_template += "[O.type][check_attributes(O,use_json=use_json)],"
// Mobs Loop
for(var/mob/M in model.contents)
if(M.dont_save || QDELETED(M))
continue
+
if(M.client)
if(!(flags & DMM_IGNORE_PLAYERS))
mob_template += "[M.type][check_attributes(M,use_json=use_json)],"
@@ -155,65 +153,68 @@
if(!(flags & DMM_IGNORE_AREAS))
var/area/m_area = model.loc
area_template = "[m_area.type][check_attributes(m_area,use_json=use_json)]"
- else area_template = "[world.area]"
+ else
+ area_template = "[world.area]"
template = "[jointext(obj_template,"")][jointext(mob_template,"")][turf_template][area_template]"
return template
-/dmm_suite/proc/check_attributes(var/atom/A,use_json=0)
+/datum/dmm_suite/proc/check_attributes(atom/A, use_json = FALSE)
var/attributes_text = "{"
var/list/attributes = list()
if(!use_json)
for(var/V in A.vars)
CHECK_TICK
- if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))) continue
+ if((!issaved(A.vars[V])) || (A.vars[V] == initial(A.vars[V])))
+ continue
attributes += var_to_dmm(A.vars[V], V)
else
- var/list/yeah = A.serialize()
+ var/list/to_encode = A.serialize()
// We'll want to write out vars that are important to the editor
// So that the map is legible as before
- for(var/thing in A.map_important_vars())
+ for(var/T in A.map_important_vars())
// Save vars that are important for the map editor, so that
// json-encoded maps are legible for standard editors
- if(A.vars[thing] != initial(A.vars[thing]))
- yeah -= thing
- attributes += var_to_dmm(A.vars[thing],thing)
+ if(A.vars[T] != initial(A.vars[T]))
+ to_encode -= T
+ attributes += var_to_dmm(A.vars[T], T)
// Remove useless info
- yeah -= "type"
- if(yeah.len)
- var/json_stuff = json_encode(yeah)
+ to_encode -= "type"
+ if(length(to_encode))
+ var/json_stuff = json_encode(to_encode)
attributes += var_to_dmm(json_stuff, "map_json_data")
- if(attributes.len == 0)
+
+ if(length(attributes) == 0)
return
// Trim a trailing semicolon - `var_to_dmm` always appends a semicolon,
// so the last one will be trailing.
- if(copytext(attributes_text, length(attributes_text)-1, 0) == "; ")
- attributes_text = copytext(attributes_text, 1, length(attributes_text)-1)
+ if(copytext(attributes_text, length(attributes_text) - 1, 0) == "; ")
+ attributes_text = copytext(attributes_text, 1, length(attributes_text) - 1)
+
attributes_text = "{[jointext(attributes,"; ")]}"
return attributes_text
-
-/dmm_suite/proc/get_model_key(var/which as num, var/key_length as num)
+/datum/dmm_suite/proc/get_model_key(which, key_length)
var/list/key = list()
- var/working_digit = which-1
+ var/working_digit = which - 1
for(var/digit_pos in key_length to 1 step -1)
- var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1)))
- working_digit-=place_value*(letter_digits.len**(digit_pos-1))
- key += letter_digits[place_value+1]
+ var/place_value = round/*floor*/(working_digit / (length(letter_digits) ** (digit_pos - 1)))
+ working_digit -= place_value * (length(letter_digits) ** (digit_pos - 1))
+ key += letter_digits[place_value + 1]
+
return jointext(key,"")
-
-/dmm_suite/proc/var_to_dmm(attr, name)
+/datum/dmm_suite/proc/var_to_dmm(attr, name)
if(istext(attr))
// dmm_encode will strip out characters that would be capable of disrupting
// parsing - namely, quotes and curly braces
return "[name] = \"[dmm_encode(attr)]\""
- else if(isnum(attr)||ispath(attr))
+ else if(isnum(attr) || ispath(attr))
return "[name] = [attr]"
- else if(isicon(attr)||isfile(attr))
+ else if(isicon(attr) || isfile(attr))
if(length("[attr]") == 0)
// The DM map reader is unable to read files that have a '' file/icon entry
return
diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm
index b41ec901573..f06a9a37f9c 100644
--- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm
+++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm
@@ -191,26 +191,27 @@
origin_tech = null
selfcharge = 1
can_charge = 0
- var/inawaymission = 1
+ // Selfcharge is enabled and disabled, and used as the away mission tracker
+ selfcharge = TRUE
-/obj/item/gun/energy/laser/awaymission_aeg/process()
- var/turf/my_loc = get_turf(src)
- if(is_away_level(my_loc.z))
- if(inawaymission)
- return ..()
+/obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload)
+ . = ..()
+ // Force update it incase it spawns outside an away mission and shouldnt be charged
+ onTransitZ(new_z = loc.z)
+
+/obj/item/gun/energy/laser/awaymission_aeg/onTransitZ(old_z, new_z)
+ if(is_away_level(new_z))
if(ismob(loc))
to_chat(loc, "Your [src] activates, starting to draw power from a nearby wireless power source.")
- inawaymission = 1
+ selfcharge = TRUE
else
- if(inawaymission)
+ if(selfcharge)
if(ismob(loc))
to_chat(loc, "Your [src] deactivates, as it is out of range from its power source.")
cell.charge = 0
- inawaymission = 0
+ selfcharge = FALSE
update_icon()
-
-
/obj/item/reagent_containers/glass/beaker/terror_black_toxin
name = "beaker 'Black Terror Venom'"
diff --git a/code/modules/awaymissions/mission_code/centcomAway.dm b/code/modules/awaymissions/mission_code/centcomAway.dm
index bd9890aa43a..92fa90891e0 100644
--- a/code/modules/awaymissions/mission_code/centcomAway.dm
+++ b/code/modules/awaymissions/mission_code/centcomAway.dm
@@ -7,32 +7,32 @@
/area/awaymission/centcomAway/general
name = "XCC-P5831"
- music = "music/ambigen3.ogg"
+ ambientsounds = list('sound/ambience/ambigen3.ogg')
/area/awaymission/centcomAway/maint
name = "XCC-P5831 Maintenance"
icon_state = "away1"
- music = "music/ambisin1.ogg"
+ ambientsounds = list('sound/ambience/ambisin1.ogg')
/area/awaymission/centcomAway/thunderdome
name = "XCC-P5831 Thunderdome"
icon_state = "away2"
- music = "music/ambisin2.ogg"
+ ambientsounds = list('sound/ambience/ambisin2.ogg')
/area/awaymission/centcomAway/cafe
name = "XCC-P5831 Kitchen Arena"
icon_state = "away3"
- music = "music/ambisin3.ogg"
+ ambientsounds = list('sound/ambience/ambisin3.ogg')
/area/awaymission/centcomAway/courtroom
name = "XCC-P5831 Courtroom"
icon_state = "away4"
- music = "music/ambisin4.ogg"
+ ambientsounds = list('sound/ambience/ambisin4.ogg')
/area/awaymission/centcomAway/hangar
name = "XCC-P5831 Hangars"
icon_state = "away4"
- music = "music/ambigen5.ogg"
+ ambientsounds = list('sound/ambience/ambigen5.ogg')
//centcomAway items
diff --git a/code/modules/awaymissions/mission_code/ruins/gps.dm b/code/modules/awaymissions/mission_code/ruins/gps.dm
new file mode 100644
index 00000000000..fa26eea5d0d
--- /dev/null
+++ b/code/modules/awaymissions/mission_code/ruins/gps.dm
@@ -0,0 +1,13 @@
+//local gps units to let the ruins be found easier.
+
+/obj/item/gps/ruin
+ name = "navigation console"
+ desc = "A console for navigation in local space, gives off a weak signal that can be picked up if sufficiently close."
+ icon = 'icons/obj/terminals.dmi'
+ icon_state = "gps_console"
+ anchored = TRUE
+ local = TRUE
+ gpstag = "Unknown Signal"
+
+/obj/item/gps/ruin/attack_hand(mob/user)
+ attack_self(user)
diff --git a/code/modules/awaymissions/mission_code/ruins/oldstation.dm b/code/modules/awaymissions/mission_code/ruins/oldstation.dm
index e939cf06f32..9489ddec45b 100644
--- a/code/modules/awaymissions/mission_code/ruins/oldstation.dm
+++ b/code/modules/awaymissions/mission_code/ruins/oldstation.dm
@@ -105,7 +105,7 @@
/obj/item/paper/fluff/ruins/oldstation/damagereport
name = "Damage Report"
- info = "*Damage Report*
Charlie Station - Intact. Loss of oxygen to eastern side of main corridor.
Theta Station - Intact. WARNING: Unknown force occupying Theta Station. Intent unknown. Species unknown. Numbers unknown.
Recommendation - Reestablish station powernet via solar array. Reestablish station atmospherics system to restore air."
/obj/item/paper/fluff/ruins/oldstation/protosuit
name = "B01-RIG Hardsuit Report"
@@ -145,7 +145,7 @@
info = "Artificial Program's report to surviving crewmembers.
Crew were placed into cryostasis on March 10th, 2445.
Crew were awoken from cryostasis around June, 2557.
\
SIGNIFICANT EVENTS OF NOTE 1: The primary radiation detectors were taken offline after 112 years due to power failure, secondary radiation detectors showed no residual \
radiation on station. Deduction, primarily detector was malfunctioning and was producing a radiation signal when there was none.
2: A data burst from a nearby Nanotrasen Space \
- Station was received, this data burst contained research data that has been uploaded to our RnD labs.
3: Unknown invasion force has occupied Delta station."
+ Station was received, this data burst contained research data that has been uploaded to our RnD labs.
3: Unknown invasion force has occupied Theta station."
/obj/item/paper/fluff/ruins/oldstation/generator_manual
name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator manual"
@@ -321,6 +321,7 @@
name = "Beta Station Atmospherics"
icon_state = "red"
has_gravity = FALSE
+ ambientsounds = ENGINEERING_SOUNDS
/area/ruin/space/ancientstation/betanorth
name = "Beta Station North Corridor"
@@ -333,6 +334,7 @@
/area/ruin/space/ancientstation/engi
name = "Charlie Station Engineering"
icon_state = "engine"
+ ambientsounds = ENGINEERING_SOUNDS
/area/ruin/space/ancientstation/comm
name = "Charlie Station Command"
@@ -350,16 +352,16 @@
name = "Charlie Station Security"
icon_state = "red"
-/area/ruin/space/ancientstation/deltacorridor
- name = "Delta Station Main Corridor"
+/area/ruin/space/ancientstation/thetacorridor
+ name = "Theta Station Main Corridor"
icon_state = "green"
/area/ruin/space/ancientstation/proto
- name = "Delta Station Prototype Lab"
+ name = "Theta Station Prototype Lab"
icon_state = "toxlab"
/area/ruin/space/ancientstation/rnd
- name = "Delta Station Research and Development"
+ name = "Theta Station Research and Development"
icon_state = "toxlab"
/area/ruin/space/ancientstation/hivebot
diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm
index 45ebf9700ca..8f2f03aea62 100644
--- a/code/modules/awaymissions/mission_code/spacehotel.dm
+++ b/code/modules/awaymissions/mission_code/spacehotel.dm
@@ -272,7 +272,7 @@
var/mob/deadbeat = D.occupant
- radio.autosay("[deadbeat], your card has been rejected. You have 30 seconds to check out.", name, zlevel = list(z))
+ radio.autosay("[deadbeat], your card has been rejected. You have 30 seconds to check out.", name)
spawn(300)
if(D.occupant == deadbeat)
// they still haven't checked out...
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index ca79a1ea2a6..b678106df5c 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -117,10 +117,8 @@
if("Peace")
to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.")
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
- for(var/mob/living/simple_animal/hostile/faithless/F in world)
- F.health = -10
- F.stat = 2
- F.icon_state = "faithless_dead"
+ for(var/mob/living/simple_animal/hostile/faithless/F in GLOB.mob_living_list)
+ F.death()
///////////////Meatgrinder//////////////
@@ -173,23 +171,9 @@
to_chat(C, "Death is not your end!")
spawn(rand(800,1200))
- if(C.stat == DEAD)
- GLOB.dead_mob_list -= C
- GLOB.living_mob_list += C
- C.stat = CONSCIOUS
- C.timeofdeath = 0
- C.setToxLoss(0)
- C.setOxyLoss(0)
- C.setCloneLoss(0)
- C.SetParalysis(0)
- C.SetStunned(0)
- C.SetWeakened(0)
- C.radiation = 0
- C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss())
- C.reagents.clear_reagents()
+ C.revive()
to_chat(C, "You have regenerated.")
C.visible_message("[usr] appears to wake from the dead, having healed all wounds.")
- C.update_canmove()
return 1
/obj/item/wildwest_communicator
@@ -234,7 +218,8 @@
to_chat(user, "The communicator buzzes, and you hear the voice again: 'Really? I think not. Get them!'")
if(option_threat)
to_chat(user, "The communicator buzzes, and you hear the voice again: 'Oh really now?' You hear a clicking sound. 'Team, get back here. We have trouble'. Then the line goes dead.")
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name == "wildwest_syndipod")
var/obj/spacepod/syndi/P = new /obj/spacepod/syndi(get_turf(L))
P.name = "Syndi Recon Pod"
@@ -247,7 +232,7 @@
used = TRUE
/obj/item/wildwest_communicator/proc/stand_down()
- for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.alive_mob_list)
W.on_alert = FALSE
/mob/living/simple_animal/hostile/syndicate/ranged/wildwest
@@ -262,6 +247,6 @@
// putting this up here so we don't say anything after deathgasp
if(can_die() && !on_alert)
say("How could you betray the Syndicate?")
- for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.alive_mob_list)
W.on_alert = TRUE
return ..(gibbed)
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index 96c5f080a14..c582508ace1 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -56,7 +56,8 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
GLOB.space_manager.remove_dirt(zlev)
log_world(" Away mission loaded: [map]")
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name != "awaystart")
continue
GLOB.awaydestinations.Add(L)
@@ -89,7 +90,8 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
//map_transition_config.Add(AWAY_MISSION_LIST)
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(L.name != "awaystart")
continue
GLOB.awaydestinations.Add(L)
@@ -172,87 +174,3 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
new /obj/effect/landmark/ruin(central_turf, src)
return TRUE
return FALSE
-
-/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
- if(!z_levels || !z_levels.len)
- WARNING("No Z levels provided - Not generating ruins")
- return
-
- for(var/zl in z_levels)
- var/turf/T = locate(1, 1, zl)
- if(!T)
- WARNING("Z level [zl] does not exist - Not generating ruins")
- return
-
- var/list/ruins = potentialRuins.Copy()
-
- var/list/forced_ruins = list() //These go first on the z level associated (same random one by default)
- var/list/ruins_availible = list() //we can try these in the current pass
- var/forced_z //If set we won't pick z level and use this one instead.
-
- //Set up the starting ruin list
- for(var/key in ruins)
- var/datum/map_template/ruin/R = ruins[key]
- if(R.cost > budget) //Why would you do that
- continue
- if(R.always_place)
- forced_ruins[R] = -1
- if(R.unpickable)
- continue
- ruins_availible[R] = R.placement_weight
-
- while(budget > 0 && (ruins_availible.len || forced_ruins.len))
- var/datum/map_template/ruin/current_pick
- var/forced = FALSE
- if(forced_ruins.len) //We have something we need to load right now, so just pick it
- for(var/ruin in forced_ruins)
- current_pick = ruin
- if(forced_ruins[ruin] > 0) //Load into designated z
- forced_z = forced_ruins[ruin]
- forced = TRUE
- break
- else //Otherwise just pick random one
- current_pick = pickweight(ruins_availible)
-
- var/placement_tries = PLACEMENT_TRIES
- var/failed_to_place = TRUE
- var/z_placed = 0
- while(placement_tries > 0)
- placement_tries--
- z_placed = pick(z_levels)
- if(!current_pick.try_to_place(forced_z ? forced_z : z_placed,whitelist))
- continue
- else
- failed_to_place = FALSE
- break
-
- //That's done remove from priority even if it failed
- if(forced)
- //TODO : handle forced ruins with multiple variants
- forced_ruins -= current_pick
- forced = FALSE
-
- if(failed_to_place)
- for(var/datum/map_template/ruin/R in ruins_availible)
- if(R.id == current_pick.id)
- ruins_availible -= R
- log_world("Failed to place [current_pick.name] ruin.")
- else
- budget -= current_pick.cost
- if(!current_pick.allow_duplicates)
- for(var/datum/map_template/ruin/R in ruins_availible)
- if(R.id == current_pick.id)
- ruins_availible -= R
- if(current_pick.never_spawn_with)
- for(var/blacklisted_type in current_pick.never_spawn_with)
- for(var/possible_exclusion in ruins_availible)
- if(istype(possible_exclusion,blacklisted_type))
- ruins_availible -= possible_exclusion
- forced_z = 0
-
- //Update the availible list
- for(var/datum/map_template/ruin/R in ruins_availible)
- if(R.cost > budget)
- ruins_availible -= R
-
- log_world("Ruin loader finished with [budget] left to spend.")
diff --git a/code/modules/buildmode/bm_mode.dm b/code/modules/buildmode/bm_mode.dm
index 0169df7cd62..bf3b52a20ce 100644
--- a/code/modules/buildmode/bm_mode.dm
+++ b/code/modules/buildmode/bm_mode.dm
@@ -28,8 +28,8 @@
return "buildmode_[key]"
/datum/buildmode_mode/proc/show_help(mob/user)
- CRASH("No help defined, yell at a coder")
to_chat(user, "There is no help defined for this mode, this is a bug.")
+ CRASH("No help defined, yell at a coder")
/datum/buildmode_mode/proc/change_settings(mob/user)
to_chat(user, "There is no configuration available for this mode")
diff --git a/code/modules/buildmode/effects/line.dm b/code/modules/buildmode/effects/line.dm
index b49d35af095..5cc88309e56 100644
--- a/code/modules/buildmode/effects/line.dm
+++ b/code/modules/buildmode/effects/line.dm
@@ -12,7 +12,7 @@
var/matrix/mat = matrix()
mat.Translate(0, 16)
mat.Scale(1, sqrt((x_offset * x_offset) + (y_offset * y_offset)) / 32)
- mat.Turn(90 - Atan2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
+ mat.Turn(90 - ATAN2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
mat.Translate(atom_a.pixel_x, atom_a.pixel_y)
transform = mat
diff --git a/code/modules/buildmode/submodes/atmos.dm b/code/modules/buildmode/submodes/atmos.dm
index b3a07374846..ac840acbead 100644
--- a/code/modules/buildmode/submodes/atmos.dm
+++ b/code/modules/buildmode/submodes/atmos.dm
@@ -9,6 +9,7 @@
var/plasma = 0
var/cdiox = 0
var/nitrox = 0
+ var/agentbx = 0
/datum/buildmode_mode/atmos/show_help(mob/user)
@@ -29,6 +30,7 @@
plasma = input(user, "Plasma ratio", "Input", 0) as num|null
cdiox = input(user, "CO2 ratio", "Input", 0) as num|null
nitrox = input(user, "N2O ratio", "Input", 0) as num|null
+ agentbx = input(user, "Agent B ratio", "Input", 0) as num|null
/datum/buildmode_mode/atmos/proc/ppratio_to_moles(ppratio)
// ideal gas equation: Pressure * Volume = Moles * r * Temperature
@@ -52,11 +54,8 @@
S.air.nitrogen = ppratio_to_moles(nitrogen)
S.air.toxins = ppratio_to_moles(plasma)
S.air.carbon_dioxide = ppratio_to_moles(cdiox)
- S.air.trace_gases.Cut()
- if(nitrox)
- var/datum/gas/TG = new /datum/gas/sleeping_agent
- TG.moles = ppratio_to_moles(nitrox)
- S.air.trace_gases += TG
+ S.air.sleeping_agent = ppratio_to_moles(nitrox)
+ S.air.agent_b = ppratio_to_moles(agentbx)
S.update_visuals()
S.air_update_turf()
else if(ctrl_click) // overwrite "default" unsimulated air
@@ -65,7 +64,8 @@
T.nitrogen = ppratio_to_moles(nitrogen)
T.toxins = ppratio_to_moles(plasma)
T.carbon_dioxide = ppratio_to_moles(cdiox)
- // no interface for trace gases on unsim turfs
+ T.sleeping_agent = ppratio_to_moles(nitrox)
+ T.agent_b = ppratio_to_moles(agentbx)
T.air_update_turf()
// admin log
diff --git a/code/modules/buildmode/submodes/copy.dm b/code/modules/buildmode/submodes/copy.dm
index 48cbb2c3cf0..95d8eee8b87 100644
--- a/code/modules/buildmode/submodes/copy.dm
+++ b/code/modules/buildmode/submodes/copy.dm
@@ -22,6 +22,6 @@
if(stored)
DuplicateObject(stored, perfectcopy=1, sameloc=0,newloc=T)
else if(right_click)
- if(ismovableatom(object)) // No copying turfs for now.
+ if(ismovable(object)) // No copying turfs for now.
to_chat(user, "[object] set as template.")
stored = object
diff --git a/code/modules/buildmode/submodes/link.dm b/code/modules/buildmode/submodes/link.dm
index 136ffad6433..25a6d92bfa3 100644
--- a/code/modules/buildmode/submodes/link.dm
+++ b/code/modules/buildmode/submodes/link.dm
@@ -46,17 +46,21 @@
if(!M.id || M.id == "")
M.id = input(user, "Please select an ID for the button", "Buildmode", "")
if(!M.id || M.id == "")
- goto line_jump
+ speed_execute()
+ return
if(P.id_tag == M.id && P.id_tag && P.id_tag != "")
P.id_tag = null
to_chat(user, "[P] unlinked.")
- goto line_jump
+ speed_execute()
+ return
if(!M.normaldoorcontrol)
if(link_lines.len && alert(user, "Warning: This will disable links to connected pod doors. Continue?", "Buildmode", "Yes", "No") == "No")
- goto line_jump
+ speed_execute()
+ return
M.normaldoorcontrol = 1
if(P.id_tag && alert(user, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No")
- goto line_jump
+ speed_execute()
+ return
P.id_tag = M.id
if(istype(link_obj, /obj/machinery/door_control) && istype(object, /obj/machinery/door/poddoor))
var/obj/machinery/door_control/M = link_obj
@@ -64,24 +68,29 @@
if(!M.id || M.id == "")
M.id = input(user, "Please select an ID for the button", "Buildmode", "")
if(!M.id || M.id == "")
- goto line_jump
+ speed_execute()
+ return
if(P.id_tag == M.id && P.id_tag && P.id_tag != "")
P.id_tag = null
to_chat(user, "[P] unlinked.")
- goto line_jump
+ speed_execute()
+ return
if(M.normaldoorcontrol)
if(link_lines.len && alert(user, "Warning: This will disable links to connected airlocks. Continue?", "Buildmode", "Yes", "No") == "No")
- goto line_jump
+ speed_execute()
+ return
M.normaldoorcontrol = 0
if(!M.id || M.id == "")
M.id = input(user, "Please select an ID for the button", "Buildmode", "")
if(!M.id || M.id == "")
- goto line_jump
+ speed_execute()
+ return
if(P.id_tag && P.id_tag != 1 && alert(user, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No")
- goto line_jump
+ speed_execute()
+ return
P.id_tag = M.id
- line_jump // For the goto
+/datum/buildmode_mode/link/proc/speed_execute() // For exiting out of hell
clear_lines()
if(istype(link_obj, /obj/machinery/door_control))
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index e1e68bd0617..8ca8bf0fbb1 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -177,6 +177,12 @@ GLOBAL_LIST_EMPTY(asset_datums)
//DEFINITIONS FOR ASSET DATUMS START HERE.
+/datum/asset/simple/tgui
+ assets = list(
+ "tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
+ "tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css'
+)
+
/datum/asset/simple/paper
assets = list(
"large_stamp-clown.png" = 'icons/paper_icons/large_stamp-clown.png',
@@ -344,3 +350,15 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/mob_hunt/send(client)
send_asset_list(client, assets, verify)
+
+// Fontawesome
+/datum/asset/simple/fontawesome
+ verify = FALSE
+ assets = list(
+ "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
+ "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
+ "fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
+ "fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
+ "font-awesome.css" = 'html/font-awesome/css/all.min.css',
+ "v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
+ )
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index 85615be1ee5..72537f8ccc3 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -20,7 +20,6 @@
var/skip_antag = FALSE //TRUE when a player declines to be included for the selection process of game mode antagonists.
var/move_delay = 1
var/moving = null
- var/adminobs = null
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
@@ -28,13 +27,6 @@
var/adminhelped = 0
- // var/gc_destroyed //Time when this object was destroyed. [Inherits from datum]
-
-#ifdef TESTING
- var/running_find_references
- var/last_find_references = 0
-#endif
-
///////////////
//SOUND STUFF//
///////////////
@@ -67,10 +59,6 @@
var/karma = 0
var/karma_spent = 0
var/karma_tab = 0
- /////////////////////////////////////////////
- // /vg/: MEDIAAAAAAAA
- // Set on login.
- var/datum/media_manager/media = null
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
@@ -93,10 +81,10 @@
// If set to true, this client can interact with atoms such as buttons and doors on top of regular machinery interaction
var/advanced_admin_interaction = FALSE
- // Has the client been varedited by an admin? [Inherits from datum now]
- // var/var_edited = FALSE
-
var/client_keysend_amount = 0
var/next_keysend_reset = 0
var/next_keysend_trip_reset = 0
var/keysend_tripped = FALSE
+
+ // Last world.time that the player tried to request their resources.
+ var/last_ui_resource_send = 0
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index efe609a8a56..ae503be111b 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -373,13 +373,11 @@
send_resources()
if(prefs.toggles & UI_DARKMODE) // activates dark mode if its flagged. -AA07
- if(establish_db_connection())
- activate_darkmode()
+ activate_darkmode()
+ else
+ // activate_darkmode() calls the CL update button proc, so we dont want it double called
+ SSchangelog.UpdatePlayerChangelogButton(src)
- if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP
- if(establish_db_connection())
- to_chat(src, "Changelog has changed since your last visit.")
- update_changelog_button()
if(prefs.toggles & DISABLE_KARMA) // activates if karma is disabled
if(establish_db_connection())
@@ -427,14 +425,20 @@
/client/proc/is_connecting_from_localhost()
var/localhost_addresses = list("127.0.0.1", "::1") // Adresses
- if(!isnull(address) && address in localhost_addresses)
+ if(!isnull(address) && (address in localhost_addresses))
return TRUE
return FALSE
//////////////
//DISCONNECT//
//////////////
+
/client/Del()
+ if(!gc_destroyed)
+ Destroy() //Clean up signals and timers.
+ return ..()
+
+/client/Destroy()
if(holder)
holder.owner = null
GLOB.admins -= src
@@ -444,7 +448,8 @@
movingmob.client_mobs_in_contents -= mob
UNSETEMPTY(movingmob.client_mobs_in_contents)
Master.UpdateTickRate()
- return ..()
+ ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening
+ return QDEL_HINT_HARDDEL_NOW
/client/proc/donator_check()
@@ -558,7 +563,7 @@
if(GLOB.panic_bunker_enabled)
var/threshold = config.panic_bunker_threshold
src << "Server is not accepting connections from never-before-seen players until player count is less than [threshold]. Please try again later."
- del(src)
+ qdel(src)
return // Dont insert or they can just go in again
var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
@@ -825,7 +830,7 @@
// IF YOU CHANGE ANYTHING IN ACTIVATE, MAKE SURE IT HAS A DEACTIVATE METHOD, -AA07
/client/proc/activate_darkmode()
///// BUTTONS /////
- update_changelog_button()
+ SSchangelog.UpdatePlayerChangelogButton(src)
/* Rpane */
winset(src, "rpane.textb", "background-color=#40628a;text-color=#FFFFFF")
winset(src, "rpane.infob", "background-color=#40628a;text-color=#FFFFFF")
@@ -857,7 +862,7 @@
/client/proc/deactivate_darkmode()
///// BUTTONS /////
- update_changelog_button()
+ SSchangelog.UpdatePlayerChangelogButton(src)
/* Rpane */
winset(src, "rpane.textb", "background-color=none;text-color=#000000")
winset(src, "rpane.infob", "background-color=none;text-color=#000000")
@@ -887,22 +892,6 @@
///// NOTIFY USER /////
to_chat(src, "Darkmode Disabled") // what a sick fuck
-// Better changelog button handling
-/client/proc/update_changelog_button()
- if(establish_db_connection())
- if(prefs.lastchangelog != GLOB.changelog_hash)
- winset(src, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold")
- else
- if(prefs.toggles & UI_DARKMODE)
- winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
- else
- winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
- else
- if(prefs.toggles & UI_DARKMODE)
- winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
- else
- winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
-
/client/proc/generate_clickcatcher()
if(!void)
void = new()
@@ -920,7 +909,39 @@
return FALSE
if(M && M.player_logged < SSD_WARNING_TIMER)
return FALSE
- to_chat(src, "Interacting with SSD players is against server rules unless you've ahelped first for permission. If you have, confirm that and proceed.")
+ to_chat(src, "Are you taking this person to cryo or giving them medical treatment? If you are, confirm that and proceed. Interacting with SSD players in other ways is against server rules unless you've ahelped first for permission.")
return TRUE
#undef SSD_WARNING_TIMER
+
+/client/verb/resend_ui_resources()
+ set name = "Reload UI Resources"
+ set desc = "Reload your UI assets if they are not working"
+ set category = "Special Verbs"
+
+ if(last_ui_resource_send > world.time)
+ to_chat(usr, "You requested your UI resource files too quickly. Please try again in [(last_ui_resource_send - world.time)/10] seconds.")
+ return
+
+ var/choice = alert(usr, "This will reload your NanoUI and TGUI resources. If you have any open UIs this may break them. Are you sure?", "Resource Reloading", "Yes", "No")
+ if(choice == "Yes")
+ // 600 deciseconds = 1 minute
+ last_ui_resource_send = world.time + 60 SECONDS
+
+ // Close their open UIs
+ SSnanoui.close_user_uis(usr)
+ SStgui.close_user_uis(usr)
+
+ // Resend the resources
+ var/datum/asset/nano_assets = get_asset_datum(/datum/asset/nanoui)
+ nano_assets.register()
+
+ var/datum/asset/tgui_assets = get_asset_datum(/datum/asset/simple/tgui)
+ tgui_assets.register()
+
+ // Clear the user's cache so they get resent.
+ // This is not fully clearing their BYOND cache, just their assets sent from the server this round
+ cache = list()
+
+ to_chat(usr, "UI resource files resent successfully. If you are still having issues, please try manually clearing your BYOND cache. This can be achieved by opening your BYOND launcher, pressing the cog in the top right, selecting preferences, going to the Games tab, and pressing 'Clear Cache'.")
+
diff --git a/code/modules/client/preference/loadout/loadout.dm b/code/modules/client/preference/loadout/loadout.dm
index 1091b38a11c..f1f0e2082de 100644
--- a/code/modules/client/preference/loadout/loadout.dm
+++ b/code/modules/client/preference/loadout/loadout.dm
@@ -9,39 +9,6 @@ GLOBAL_LIST_EMPTY(gear_datums)
category = cat
..()
-/hook/startup/proc/populate_gear_list()
- //create a list of gear datums to sort
- for(var/geartype in subtypesof(/datum/gear))
- var/datum/gear/G = geartype
-
- var/use_name = initial(G.display_name)
- var/use_category = initial(G.sort_category)
-
- if(G == initial(G.subtype_path))
- continue
-
- if(!use_name)
- error("Loadout - Missing display name: [G]")
- continue
- if(!initial(G.cost))
- error("Loadout - Missing cost: [G]")
- continue
- if(!initial(G.path))
- error("Loadout - Missing path definition: [G]")
- continue
-
- if(!GLOB.loadout_categories[use_category])
- GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category)
- var/datum/loadout_category/LC = GLOB.loadout_categories[use_category]
- GLOB.gear_datums[use_name] = new geartype
- LC.gear[use_name] = GLOB.gear_datums[use_name]
-
- GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories)
- for(var/loadout_category in GLOB.loadout_categories)
- var/datum/loadout_category/LC = GLOB.loadout_categories[loadout_category]
- LC.gear = sortAssoc(LC.gear)
- return 1
-
/datum/gear
var/display_name //Name/index. Must be unique.
var/description //Description of this gear. If left blank will default to the description of the pathed item.
diff --git a/code/modules/client/preference/loadout/loadout_accessories.dm b/code/modules/client/preference/loadout/loadout_accessories.dm
index 09cc082dc5d..b9318fd9e8c 100644
--- a/code/modules/client/preference/loadout/loadout_accessories.dm
+++ b/code/modules/client/preference/loadout/loadout_accessories.dm
@@ -163,41 +163,41 @@
display_name = "armband, blue-yellow"
path = /obj/item/clothing/accessory/armband/yb
-/datum/gear/accessory/armband_sec
+/datum/gear/accessory/armband_job
+ subtype_path = /datum/gear/accessory/armband_job
+ subtype_cost_overlap = FALSE
+
+/datum/gear/accessory/armband_job/sec
display_name = " armband, security"
path = /obj/item/clothing/accessory/armband/sec
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Brig Physician", "Security Pod Pilot")
-/datum/gear/accessory/armband_cargo
+/datum/gear/accessory/armband_job/cargo
display_name = "cargo armband"
path = /obj/item/clothing/accessory/armband/cargo
allowed_roles = list("Quartermaster","Cargo Technician", "Shaft Miner")
-/datum/gear/accessory/armband_medical
+/datum/gear/accessory/armband_job/medical
display_name = "armband, medical"
path = /obj/item/clothing/accessory/armband/med
allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Coroner", "Paramedic", "Brig Physician")
-/datum/gear/accessory/armband_emt
+/datum/gear/accessory/armband_job/emt
display_name = "armband, EMT"
path = /obj/item/clothing/accessory/armband/medgreen
allowed_roles = list("Paramedic", "Brig Physician")
-/datum/gear/accessory/armband_engineering
+/datum/gear/accessory/armband_job/engineering
display_name = "armband, engineering"
path = /obj/item/clothing/accessory/armband/engine
allowed_roles = list("Chief Engineer","Station Engineer", "Life Support Specialist")
-/datum/gear/accessory/armband_hydro
+/datum/gear/accessory/armband_job/hydro
display_name = "armband, hydroponics"
path = /obj/item/clothing/accessory/armband/hydro
allowed_roles = list("Botanist")
-/datum/gear/accessory/armband_sci
+/datum/gear/accessory/armband_job/sci
display_name = "armband, science"
path = /obj/item/clothing/accessory/armband/science
allowed_roles = list("Research Director","Scientist", "Roboticist")
-
-
-
-
diff --git a/code/modules/client/preference/loadout/loadout_general.dm b/code/modules/client/preference/loadout/loadout_general.dm
index 50105813fd6..8c08063ad7e 100644
--- a/code/modules/client/preference/loadout/loadout_general.dm
+++ b/code/modules/client/preference/loadout/loadout_general.dm
@@ -29,7 +29,7 @@
/datum/gear/sechud
display_name = "a classic security HUD"
path = /obj/item/clothing/glasses/hud/security
- allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent")
+ allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent","Magistrate")
/datum/gear/matches
display_name = "a box of matches"
@@ -42,7 +42,7 @@
/datum/gear/doublecards
display_name = "a double deck of standard cards"
path = /obj/item/deck/doublecards
-
+
/datum/gear/tarot
display_name = "a deck of tarot cards"
path = /obj/item/deck/tarot
diff --git a/code/modules/client/preference/loadout/loadout_hat.dm b/code/modules/client/preference/loadout/loadout_hat.dm
index 7d6275e09e4..4993c8502ea 100644
--- a/code/modules/client/preference/loadout/loadout_hat.dm
+++ b/code/modules/client/preference/loadout/loadout_hat.dm
@@ -42,11 +42,6 @@
display_name = "fedora, brown"
path = /obj/item/clothing/head/fedora/brownfedora
-/datum/gear/hat/beretsec
- display_name = "security beret"
- path = /obj/item/clothing/head/beret/sec
- allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
-
/datum/gear/hat/capcsec
display_name = "security corporate cap"
path = /obj/item/clothing/head/soft/sec/corp
@@ -113,32 +108,51 @@
display_name = "cowboy hat, pink"
path = /obj/item/clothing/head/cowboyhat/pink
-/datum/gear/hat/pr_beret
+/datum/gear/hat/beret_purple
display_name = "beret, purple"
path = /obj/item/clothing/head/beret/purple_normal
-/datum/gear/hat/bl_beret
+/datum/gear/hat/beret_black
display_name = "beret, black"
path = /obj/item/clothing/head/beret/black
-/datum/gear/hat/blu_beret
+/datum/gear/hat/beret_blue
display_name = "beret, blue"
path = /obj/item/clothing/head/beret/blue
-/datum/gear/hat/red_beret
+/datum/gear/hat/beret_red
display_name = "beret, red"
path = /obj/item/clothing/head/beret
-/datum/gear/hat/sci_beret
+/datum/gear/hat/beret_job
+ subtype_path = /datum/gear/hat/beret_job
+ subtype_cost_overlap = FALSE
+
+/datum/gear/hat/beret_job/sec
+ display_name = "security beret"
+ path = /obj/item/clothing/head/beret/sec
+ allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
+
+/datum/gear/hat/beret_job/sci
display_name = "science beret"
path = /obj/item/clothing/head/beret/sci
allowed_roles = list("Research Director", "Scientist")
-/datum/gear/hat/med_beret
+/datum/gear/hat/beret_job/med
display_name = "medical beret"
path = /obj/item/clothing/head/beret/med
allowed_roles = list("Chief Medical Officer", "Medical Doctor" , "Virologist", "Brig Physician" , "Coroner")
+/datum/gear/hat/beret_job/eng
+ display_name = "engineering beret"
+ path = /obj/item/clothing/head/beret/eng
+ allowed_roles = list("Chief Engineer", "Station Engineer")
+
+/datum/gear/hat/beret_job/atmos
+ display_name = "atmospherics beret"
+ path = /obj/item/clothing/head/beret/atmos
+ allowed_roles = list("Chief Engineer", "Life Support Specialist")
+
/datum/gear/hat/surgicalcap_purple
display_name = "surgical cap, purple"
path = /obj/item/clothing/head/surgery/purple
diff --git a/code/modules/client/preference/loadout/loadout_suit.dm b/code/modules/client/preference/loadout/loadout_suit.dm
index 32a9bae99e7..57e7ea63414 100644
--- a/code/modules/client/preference/loadout/loadout_suit.dm
+++ b/code/modules/client/preference/loadout/loadout_suit.dm
@@ -175,32 +175,36 @@
display_name = "regal shawl"
path = /obj/item/clothing/suit/mantle/regal
-/datum/gear/suit/captain_cloak
+/datum/gear/suit/mantle/job
+ subtype_path = /datum/gear/suit/mantle/job
+ subtype_cost_overlap = FALSE
+
+/datum/gear/suit/mantle/job/captain
display_name = "mantle, captain"
path = /obj/item/clothing/suit/mantle/armor/captain
allowed_roles = list("Captain")
-/datum/gear/suit/ce_mantle
+/datum/gear/suit/mantle/job/ce
display_name = "mantle, chief engineer"
path = /obj/item/clothing/suit/mantle/chief_engineer
allowed_roles = list("Chief Engineer")
-/datum/gear/suit/cmo_mantle
+/datum/gear/suit/mantle/job/cmo
display_name = "mantle, chief medical officer"
path = /obj/item/clothing/suit/mantle/labcoat/chief_medical_officer
allowed_roles = list("Chief Medical Officer")
-/datum/gear/suit/armored_shawl
+/datum/gear/suit/mantle/job/hos
display_name = "mantle, head of security"
path = /obj/item/clothing/suit/mantle/armor
allowed_roles = list("Head of Security")
-/datum/gear/suit/hop_shawl
+/datum/gear/suit/mantle/job/hop
display_name = "mantle, head of personnel"
path = /obj/item/clothing/suit/mantle/armor/head_of_personnel
allowed_roles = list("Head of Personnel")
-/datum/gear/suit/rd_mantle
+/datum/gear/suit/mantle/job/rd
display_name = "mantle, research director"
path = /obj/item/clothing/suit/mantle/labcoat
allowed_roles = list("Research Director")
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index ff3a5168868..12203b8155f 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
return C.player_age
else
return max(0, days - C.player_age)
- return 0
#define MAX_SAVE_SLOTS 30 // Save slots for regular players
#define MAX_SAVE_SLOTS_MEMBER 30 // Save slots for BYOND members
@@ -79,7 +78,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/last_id
//game-preferences
- var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
+ var/lastchangelog = "1" //Saved changlog timestamp (unix epoch) to detect if there was a change. Dont set this to 0 unless you want the last changelog date to be 4x longer than the expected lifespan of the universe.
var/exp
var/ooccolor = "#b82e00"
var/list/be_special = list() //Special role selection
@@ -189,6 +188,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
// OOC Metadata:
var/metadata = ""
var/slot_name = ""
+ var/saved = FALSE // Indicates whether the character comes from the database or not
// Whether or not to use randomized character slots
var/randomslot = 0
@@ -200,7 +200,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/unlock_content = 0
//Gear stuff
- var/list/gear = list()
+ var/list/loadout_gear = list()
var/gear_tab = "General"
// Parallax
var/parallax = PARALLAX_HIGH
@@ -264,10 +264,12 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "(Always Randomize) "
dat += "
"
dat += "
"
- dat += "Slot [slot_name] - "
+ dat += "Slot [default_slot][saved ? "" : " (empty)"] "
dat += "Load slot - "
dat += "Save slot - "
dat += "Reload slot"
+ if(saved)
+ dat += " - Clear slot"
dat += "
"
dat += "
"
dat += "
"
@@ -398,6 +400,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
organ_name = "right hand"
if("eyes")
organ_name = "eyes"
+ if("ears")
+ organ_name = "ears"
if("heart")
organ_name = "heart"
if("lungs")
@@ -489,7 +493,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "You are banned from special roles."
be_special = list()
else
- for(var/i in special_roles)
+ for(var/i in GLOB.special_roles)
if(jobban_isbanned(user, i))
dat += "Be [capitalize(i)]: \[BANNED] "
else if(!player_old_enough_antag(user.client, i))
@@ -508,9 +512,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if(TAB_GEAR)
var/total_cost = 0
var/list/type_blacklist = list()
- if(gear && gear.len)
- for(var/i = 1, i <= gear.len, i++)
- var/datum/gear/G = GLOB.gear_datums[gear[i]]
+ if(loadout_gear && loadout_gear.len)
+ for(var/i = 1, i <= loadout_gear.len, i++)
+ var/datum/gear/G = GLOB.gear_datums[loadout_gear[i]]
if(G)
if(!G.subtype_cost_overlap)
if(G.subtype_path in type_blacklist)
@@ -543,7 +547,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "
"
for(var/gear_name in LC.gear)
var/datum/gear/G = LC.gear[gear_name]
- var/ticked = (G.display_name in gear)
+ var/ticked = (G.display_name in loadout_gear)
if(G.donator_tier > user.client.donator_level)
dat += "
[G.display_name]
"
else
@@ -576,10 +580,10 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
/datum/preferences/proc/get_gear_metadata(var/datum/gear/G)
- . = gear[G.display_name]
+ . = loadout_gear[G.display_name]
if(!.)
. = list()
- gear[G.display_name] = .
+ loadout_gear[G.display_name] = .
/datum/preferences/proc/get_tweak_metadata(var/datum/gear/G, var/datum/gear_tweak/tweak)
var/list/metadata = get_gear_metadata(G)
@@ -622,6 +626,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if(job.admin_only)
continue
+ if(job.hidden_from_job_prefs)
+ continue
+
index += 1
if((index >= limit) || (job.title in splitJobs))
if((index < limit) && (lastJob != null))
@@ -721,7 +728,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
HTML += "
"
for(var/i = 1, i < (limit - index), i += 1) // Finish the column so it is even
- HTML += "
 
 
"
+ HTML += "
 
 
"
HTML += "
"
@@ -847,9 +854,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
return 1
/datum/preferences/proc/ShowDisabilityState(mob/user, flag, label)
- var/datum/species/S = GLOB.all_species[species]
- if(flag == DISABILITY_FLAG_FAT && !(CAN_BE_FAT in S.species_traits))
- return "
"
+ QDEL_NULL(M)
manualcount++
- QDEL_NULL(M)
dat += "
"
dat += " (Return to main menu) "
@@ -206,7 +207,7 @@
var/obj/item/barcodescanner/scanner = W
scanner.computer = src
to_chat(user, "[scanner]'s associated machine has been set to [src].")
- audible_message("[src] lets out a low, short blip.", 2)
+ audible_message("[src] lets out a low, short blip.", hearing_distance = 2)
return 1
else
return ..()
@@ -223,13 +224,13 @@
else
var/pn = text2num(href_list["pagenum"])
if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
+ page_num = clamp(pn, 1, num_pages)
if(href_list["page"])
if(num_pages == 0)
page_num = 1
else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+ page_num = clamp(text2num(href_list["page"]), 1, num_pages)
if(href_list["settitle"])
var/newtitle = input("Enter a title to search for:") as text|null
if(newtitle)
@@ -251,7 +252,7 @@
if(href_list["search"])
num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ num_pages = CEILING(num_results/LIBRARY_BOOKS_PER_PAGE, 1)
page_num = 1
screenstate = 4
@@ -412,7 +413,7 @@
return
if(bibledelay)
- audible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
+ visible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
else
bibledelay = 1
spawn(60)
@@ -462,4 +463,5 @@
B.author = newbook.author
B.dat = newbook.content
B.icon_state = "book[rand(1,16)]"
+ B.has_drm = TRUE
visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
diff --git a/code/modules/library/computers/public.dm b/code/modules/library/computers/public.dm
index f94369b11b7..3c5116bc074 100644
--- a/code/modules/library/computers/public.dm
+++ b/code/modules/library/computers/public.dm
@@ -75,7 +75,7 @@
else
var/pn = text2num(href_list["pagenum"])
if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
+ page_num = clamp(pn, 1, num_pages)
if(href_list["settitle"])
var/newtitle = input("Enter a title to search for:") as text|null
@@ -100,11 +100,11 @@
if(num_pages == 0)
page_num = 1
else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+ page_num = clamp(text2num(href_list["page"]), 1, num_pages)
if(href_list["search"])
num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ num_pages = CEILING(num_results/LIBRARY_BOOKS_PER_PAGE, 1)
page_num = 1
screenstate = 1
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index a7dd148b51a..e74625c8715 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -151,6 +151,8 @@
var/carved = 0 // Has the book been hollowed out for use as a secret storage item?
var/forbidden = 0 // Prevent ordering of this book. (0=no, 1=yes, 2=emag only)
var/obj/item/store // What's in the book?
+ /// Book DRM. If this var is TRUE, it cannot be scanned and re-uploaded
+ var/has_drm = FALSE
/obj/item/book/attack_self(var/mob/user as mob)
if(carved)
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 65fadaa9b45..0c23a0c5800 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -3,11 +3,6 @@
GLOBAL_DATUM_INIT(library_catalog, /datum/library_catalog, new())
GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion"))
-
-/hook/startup/proc/load_manuals()
- GLOB.library_catalog.initialize()
- return 1
-
/*
* Borrowbook datum
*/
@@ -65,7 +60,7 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
/datum/library_catalog
var/list/cached_books = list()
-/datum/library_catalog/proc/initialize()
+/datum/library_catalog/New()
var/newid=1
for(var/typepath in subtypesof(/obj/item/book/manual))
var/obj/item/book/B = new typepath(null)
@@ -155,6 +150,11 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
power_change()
return
if(istype(I, /obj/item/book))
+ // NT with those pesky DRM schemes
+ var/obj/item/book/B = I
+ if(B.has_drm)
+ atom_say("Copyrighted material detected. Scanner is unable to copy book to memory.")
+ return FALSE
user.drop_item()
I.forceMove(src)
return 1
diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm
index ff4bc517979..fa848700557 100644
--- a/code/modules/lighting/lighting_atom.dm
+++ b/code/modules/lighting/lighting_atom.dm
@@ -38,7 +38,7 @@
if(!light_power || !light_range) // We won't emit light anyways, destroy the light source.
QDEL_NULL(light)
else
- if(!ismovableatom(loc)) // We choose what atom should be the top atom of the light here.
+ if(!ismovable(loc)) // We choose what atom should be the top atom of the light here.
. = src
else
. = loc
diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm
index bc521114d56..57302b5b168 100644
--- a/code/modules/lighting/lighting_corner.dm
+++ b/code/modules/lighting/lighting_corner.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
var/cache_b = LIGHTING_SOFT_THRESHOLD
var/cache_mx = 0
-/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
+/datum/lighting_corner/New(turf/new_turf, diagonal)
. = ..()
masters = list()
masters[new_turf] = turn(diagonal, 180)
@@ -79,15 +79,16 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
active = FALSE
var/turf/T
var/thing
- for (thing in masters)
+ for(thing in masters)
T = thing
if(T.lighting_object)
active = TRUE
+ return
// God that was a mess, now to do the rest of the corner code! Hooray!
-/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b)
+/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b)
- if((abs(delta_r)+abs(delta_g)+abs(delta_b)) == 0)
+ if(!(delta_r || delta_g || delta_b)) // 0 is falsey ok
return
lum_r += delta_r
@@ -96,10 +97,10 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
if(!needs_update)
needs_update = TRUE
- GLOB.lighting_update_corners += src
+ SSlighting.corners_queue += src
/datum/lighting_corner/proc/update_objects()
- // Cache these values a head of time so 4 individual lighting objects don't all calculate them individually.
+ // Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually.
var/lum_r = src.lum_r
var/lum_g = src.lum_g
var/lum_b = src.lum_b
@@ -122,19 +123,18 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
#endif
cache_mx = round(mx, LIGHTING_ROUND_VALUE)
- for (var/TT in masters)
+ for(var/TT in masters)
var/turf/T = TT
- if(T.lighting_object)
- if(!T.lighting_object.needs_update)
- T.lighting_object.needs_update = TRUE
- GLOB.lighting_update_objects += T.lighting_object
+ if(T.lighting_object && !T.lighting_object.needs_update)
+ T.lighting_object.needs_update = TRUE
+ SSlighting.objects_queue += T.lighting_object
/datum/lighting_corner/dummy/New()
return
-/datum/lighting_corner/Destroy(var/force)
+/datum/lighting_corner/Destroy(force)
if(!force)
return QDEL_HINT_LETMELIVE
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index ea3e954fa6e..168a95c07f2 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -5,7 +5,7 @@
icon = LIGHTING_ICON
icon_state = "transparent"
- color = LIGHTING_BASE_MATRIX
+ color = null //we manually set color in init instead
plane = LIGHTING_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = LIGHTING_LAYER
@@ -18,6 +18,9 @@
/atom/movable/lighting_object/Initialize(mapload)
. = ..()
verbs.Cut()
+ //We avoid setting this in the base as if we do then the parent atom handling will add_atom_color it and that
+ //is totally unsuitable for this object, as we are always changing it's colour manually
+ color = LIGHTING_BASE_MATRIX
myturf = loc
if(myturf.lighting_object)
@@ -29,11 +32,11 @@
S.update_starlight()
needs_update = TRUE
- GLOB.lighting_update_objects += src
+ SSlighting.objects_queue += src
-/atom/movable/lighting_object/Destroy(var/force)
+/atom/movable/lighting_object/Destroy(force)
if(force)
- GLOB.lighting_update_objects -= src
+ SSlighting.objects_queue -= src
if(loc != myturf)
var/turf/oldturf = get_turf(myturf)
var/turf/newturf = get_turf(loc)
@@ -143,6 +146,6 @@
return
// Override here to prevent things accidentally moving around overlays.
-/atom/movable/lighting_object/forceMove(atom/destination, var/no_tp=FALSE, var/harderforce = FALSE)
+/atom/movable/lighting_object/forceMove(atom/destination, no_tp = FALSE, harderforce = FALSE)
if(harderforce)
. = ..()
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index 8e54531f901..9398bd9683c 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -29,7 +29,7 @@
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
-/datum/light_source/New(var/atom/owner, var/atom/top)
+/datum/light_source/New(atom/owner, atom/top)
source_atom = owner // Set our new owner.
LAZYADD(source_atom.light_sources, src)
top_atom = top
@@ -43,12 +43,10 @@
light_range = source_atom.light_range
light_color = source_atom.light_color
- parse_light_color()
+ PARSE_LIGHT_COLOR(src)
update()
- return ..()
-
/datum/light_source/Destroy(force)
remove_lum()
if(source_atom)
@@ -58,7 +56,7 @@
LAZYREMOVE(top_atom.light_sources, src)
if(needs_update)
- GLOB.lighting_update_lights -= src
+ SSlighting.sources_queue -= src
. = ..()
@@ -67,13 +65,13 @@
// Actually that'd be great if you could!
#define EFFECT_UPDATE(level) \
if(needs_update == LIGHTING_NO_UPDATE) \
- GLOB.lighting_update_lights += src; \
+ SSlighting.sources_queue += src; \
if(needs_update < level) \
needs_update = level; \
// This proc will cause the light source to update the top atom, and add itself to the update queue.
-/datum/light_source/proc/update(var/atom/new_top_atom)
+/datum/light_source/proc/update(atom/new_top_atom)
// This top atom is different.
if(new_top_atom && new_top_atom != top_atom)
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
@@ -94,17 +92,6 @@
/datum/light_source/proc/vis_update()
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
-// Decompile the hexadecimal colour into lumcounts of each perspective.
-/datum/light_source/proc/parse_light_color()
- if(light_color)
- lum_r = GetRedPart (light_color) / 255
- lum_g = GetGreenPart (light_color) / 255
- lum_b = GetBluePart (light_color) / 255
- else
- lum_r = 1
- lum_g = 1
- lum_b = 1
-
// Macro that applies light to a new corner.
// It is a macro in the interest of speed, yet not having to copy paste it.
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
@@ -154,7 +141,7 @@
effect_str = null
-/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
+/datum/light_source/proc/recalc_corner(datum/lighting_corner/C)
LAZYINITLIST(effect_str)
if(effect_str[C]) // Already have one.
REMOVE_CORNER(C)
@@ -212,7 +199,7 @@
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
- parse_light_color()
+ PARSE_LIGHT_COLOR(src)
update = TRUE
else if(applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
@@ -233,9 +220,14 @@
var/oldlum = source_turf.luminosity
source_turf.luminosity = CEILING(light_range, 1)
for(T in view(CEILING(light_range, 1), source_turf))
- for (thing in T.get_corners(source_turf))
- C = thing
- corners[C] = 0
+ if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources))
+ continue
+ if(!T.has_opaque_atom)
+ if(!T.lighting_corners_initialised)
+ T.generate_missing_corners()
+ for(thing in T.corners)
+ C = thing
+ corners[C] = 0
turfs += T
source_turf.luminosity = oldlum
diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm
index c2198cea650..5483eebf4e1 100644
--- a/code/modules/lighting/lighting_turf.dm
+++ b/code/modules/lighting/lighting_turf.dm
@@ -57,7 +57,7 @@
C.active = TRUE
// Used to get a scaled lumcount.
-/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
+/turf/proc/get_lumcount(minlum = 0, maxlum = 1)
if(!lighting_object)
return 1
@@ -102,7 +102,7 @@
recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates.
reconsider_lights()
-/turf/proc/change_area(var/area/old_area, var/area/new_area)
+/turf/proc/change_area(area/old_area, area/new_area)
if(SSlighting.initialized)
if(new_area.dynamic_lighting != old_area.dynamic_lighting)
if(new_area.dynamic_lighting)
@@ -110,16 +110,6 @@
else
lighting_clear_overlay()
-/turf/proc/get_corners()
- if(!IS_DYNAMIC_LIGHTING(src) && !light_sources)
- return null
- if(!lighting_corners_initialised)
- generate_missing_corners()
- if(has_opaque_atom)
- return null // Since this proc gets used in a for loop, null won't be looped though.
-
- return corners
-
/turf/proc/generate_missing_corners()
if(!IS_DYNAMIC_LIGHTING(src) && !light_sources)
return
@@ -132,4 +122,3 @@
continue
corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i])
-
diff --git a/code/modules/logic/converter.dm b/code/modules/logic/converter.dm
deleted file mode 100644
index c54e3fe4882..00000000000
--- a/code/modules/logic/converter.dm
+++ /dev/null
@@ -1,143 +0,0 @@
-
-//////////////////////////////////
-// Converter Gate //
-//////////////////////////////////
-
-/*
- This gate is special enough to warrant its own file, as it overrides a lot of the logic_gate procs as well as adds a new one.
- - CONVERT Gates convert signaler and logic signals, to allow logic gates to actually be used in tandem with assemblies and station equipment like doors.
- - While technically a mono-input device, the input and output are actually completely different types of signals, and thus incompatible without this gate.
- - A signaler must be attached manually before the gate is fully functional, and will retain any frequency and code settings it had when attached.
- - You can adjust these settings through a link in the multitool menu, but the receiving mode is automatically controlled by the converter.
- - While attached, the ability to manually send the signal on the signaler through its menu is also disabled, to avoid messing up the logic system.
-*/
-
-//CONVERT Gate
-/obj/machinery/logic_gate/convert
- name = "CONVERT Gate"
- desc = "Converts signals between radio and logic types, allowing for signaller input/output from logic systems."
- icon_state = "logic_convert"
- mono_input = 1
-
- var/logic_output = 0 //When set to 1, the logic signal is the output. When set to 0, the logic signal is the input.
- var/obj/item/assembly/signaler/attached_signaler = null
-
-/obj/machinery/logic_gate/convert/handle_logic()
- output_state = input1_state
- return
-
-/obj/machinery/logic_gate/convert/attackby(obj/item/O, mob/user, params)
- if(tamperproof) //Extra precaution to avoid people attaching/removing signalers from tamperproofed converters
- return
- if(istype(O, /obj/item/assembly/signaler))
- var/obj/item/assembly/signaler/S = O
- if(S.secured)
- to_chat(user, "The [S] is already secured.")
- return
- if(attached_signaler)
- to_chat(user, "There is already a device attached, remove it first.")
- return
- user.unEquip(S)
- S.forceMove(src)
- S.holder = src
- S.toggle_secure()
- if(logic_output) //Make sure we are set to receive if the converter is set to output logic, and send if the converter is set to accept logic input
- S.receiving = 1
- else
- S.receiving = 0
- attached_signaler = S
- to_chat(user, "You attach \the [S] to the I/O connection port and secure it.")
- return
- if(attached_signaler && istype(O, /obj/item/screwdriver)) //Makes sure we remove the attached signaler before we can open up and deconstruct the machine
- var/obj/item/assembly/signaler/S = attached_signaler
- attached_signaler = null
- S.forceMove(get_turf(src))
- S.holder = null
- S.toggle_secure()
- to_chat(user, "You unsecure and detach \the [S] from the I/O connection port.")
- return
- return ..()
-
-/obj/machinery/logic_gate/convert/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- var/logic_state_string
- var/menu_contents = {"
-
- "}
- return menu_contents
-
-/obj/machinery/logic_gate/convert/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- if("toggle_logic" in href_list)
- logic_output = !logic_output
- if(attached_signaler) //If we have a signaler attached, make sure we update it to send/receive when we change the logic signal desgination
- if(logic_output)
- attached_signaler.receiving = 1
- else
- attached_signaler.receiving = 0
- if(("adjust_signaler" in href_list) && attached_signaler) //Make sure that we have a signaler attached to handle this one, otherwise ignore this command
- attached_signaler.interact(user, 1)
- update_multitool_menu(user)
-
-/obj/machinery/logic_gate/convert/receive_signal(datum/signal/signal, receive_method, receive_param)
- if(logic_output)
- if(attached_signaler)
- attached_signaler.receive_signal(signal)
- return
- else
- ..()
-
-/obj/machinery/logic_gate/convert/handle_output()
- if(logic_output)
- ..()
- else
- if(attached_signaler && (output_state == LOGIC_ON || output_state == LOGIC_FLICKER))
- attached_signaler.signal()
- return
-
-/obj/machinery/logic_gate/convert/proc/process_activation(var/obj/item/D)
- if(!logic_output) //Don't bother if our input is a logic signal
- return
- if(D == attached_signaler) //Ignore if we somehow got called by a device that isn't what we have attached
- input1_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input1_state == LOGIC_FLICKER)
- input1_state = LOGIC_OFF
- return
diff --git a/code/modules/logic/dual_input.dm b/code/modules/logic/dual_input.dm
deleted file mode 100644
index b8f915ff46d..00000000000
--- a/code/modules/logic/dual_input.dm
+++ /dev/null
@@ -1,100 +0,0 @@
-
-//////////////////////////////////
-// Dual-Input Gates //
-//////////////////////////////////
-
-
-// OR Gate
-/obj/machinery/logic_gate/or
- name = "OR Gate"
- desc = "Outputs ON when at least one input is ON."
- icon_state = "logic_or"
-
-/obj/machinery/logic_gate/or/handle_logic()
- if(input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER || input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER)
- if(input1_state == LOGIC_ON || input2_state == LOGIC_ON) //continuous signal takes priority in determining what to output
- output_state = LOGIC_ON
- else
- output_state = LOGIC_FLICKER
- else //Both inputs were off, so input is off
- output_state = LOGIC_OFF
- return
-
-// AND Gate
-/obj/machinery/logic_gate/and
- name = "AND Gate"
- desc = "Outputs ON only when both inputs are ON."
- icon_state = "logic_and"
-
-/obj/machinery/logic_gate/and/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER))
- if(input1_state == LOGIC_ON && input2_state == LOGIC_ON) //only output a continuous signal when both inputs are continuous signals
- output_state = LOGIC_ON
- else
- output_state = LOGIC_FLICKER
- else //At least one input was off, so output is off
- output_state = LOGIC_OFF
- return
-
-// NAND Gate
-/obj/machinery/logic_gate/nand
- name = "NAND Gate"
- desc = "Outputs OFF only when both inputs are ON."
- output_state = LOGIC_ON
- icon_state = "logic_nand"
-
-/obj/machinery/logic_gate/nand/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER))
- output_state = LOGIC_OFF //Both inputs are ON/FLICKER, so output is off
- else
- output_state = LOGIC_ON //This can only output continuous signals
- return
-
-// NOR Gate
-/obj/machinery/logic_gate/nor
- name = "NOR Gate"
- desc = "Outputs OFF when at least one input is ON."
- icon_state = "logic_nor"
- output_state = LOGIC_ON
-
-/obj/machinery/logic_gate/nor/handle_logic()
- if(input1_state == LOGIC_OFF && input2_state == LOGIC_OFF) //Both inputs are OFF, so output is ON
- output_state = LOGIC_ON //This can only output continuous signals
- else
- output_state = LOGIC_OFF
- return
-
-// XOR Gate
-/obj/machinery/logic_gate/xor
- name = "XOR Gate"
- desc = "Outputs ON when only one input is ON."
- icon_state = "logic_xor"
-
-/obj/machinery/logic_gate/xor/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_OFF)) //Only input1 is ON/FLICKER, so output matches input1
- output_state = input1_state
- else if((input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER) && (input1_state == LOGIC_OFF)) //Only input2 is ON/FLICKER, so output matches input2
- output_state = input2_state
- else //Both inputs are ON or OFF, so output is OFF
- output_state = LOGIC_OFF
- return
-
-
-// XNOR Gate
-/obj/machinery/logic_gate/xnor
- name = "XNOR Gate"
- desc = "Outputs ON when both inputs are ON or OFF."
- icon_state = "logic_xnor"
- output_state = LOGIC_ON
-
-/obj/machinery/logic_gate/xnor/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER)) //Both inputs are ON/FLICKER
- if(input1_state == LOGIC_ON && input2_state == LOGIC_ON) //Only continuous signal when both inputs are ON
- output_state = LOGIC_ON
- else //If at least one input is FLICKER, output FLICKER
- output_state = LOGIC_FLICKER
- else if(input1_state == LOGIC_OFF && input2_state == LOGIC_OFF) //Both inputs are OFF
- output_state = LOGIC_ON //Always continuous in this case
- else //Only one input is ON/FLICKER
- output_state = LOGIC_OFF
- return
diff --git a/code/modules/logic/logic_base.dm b/code/modules/logic/logic_base.dm
deleted file mode 100644
index 542cb09bc7f..00000000000
--- a/code/modules/logic/logic_base.dm
+++ /dev/null
@@ -1,284 +0,0 @@
-
-/obj/machinery/logic_gate
- name = "Logic Base"
- desc = "This does nothing except connect to things. Highly illogical, report to a coder at once if you see this in-game."
- icon = 'icons/obj/computer3.dmi'
- icon_state = "serverframe"
- density = 1
- anchored = 1
-
- settagwhitelist = list("input1_id_tag", "input2_id_tag", "output_id_tag")
-
- var/tamperproof = 0 //if set, will make the machine unable to be destroyed, adjusted, etc. via in-game interaction (USE ONLY FOR MAPPING STUFF)
- var/mono_input = 0 //if set, will ignore input2
-
- var/datum/radio_frequency/radio_connection
- var/frequency = 0
-
- /*
- Some notes on Input/Output:
- - Multiple things can be linked to the same input or output tag, just like how wires can connect multiple sources and receivers.
- - For inputs, only the last signal received BEFORE a process() call will be used in the logic handling.
- - Input states are updated immediately whenever an input signal is received, so it is possible to update multiple times within a single process cycle.
- - This means if you have multiple connected inputs, but the last signal received before the process() call is OFF, it won't matter if the others are both ON.
- - For this reason, please set up your logic properly. You can theoretically chain these infinitely, so there's no need to link multiple things to a single input.
- - For outputs, the signal will attempt to be sent out every process() call, to ensure newly connected things are updated within one process cycle
- - Connecting an output to multiple inputs should not cause issues, as long as you don't have multiple connections to a given input (see previous notes on inputs).
- - The output state is determined immediately preceeding the signal broadcast, using the input states at the time of the process() call, not when a signal is received.
- - Because of how the process cycle works, it is possible that it may take multiple cycles for a signal to fully propogate through a logic chain.
- - This is because machines attempt to process in the order they were added to the scheduler.
- - Building the logic gates at the end of the chain first may cause delays in signal propogation.
- If you take all this into consideration when linking and using logic machinery, you should have no unexpected issues with input/output. Your design flaws are on you though.
- */
-
- var/input1_id_tag = null
- var/input1_state = LOGIC_OFF
- var/input2_id_tag = null
- var/input2_state = LOGIC_OFF
- var/output_id_tag = null
- var/output_state = LOGIC_OFF
-
-/obj/machinery/logic_gate/New()
- if(tamperproof) //doing this during New so we don't have to worry about forgetting to set these vars during editting / defining
- resistance_flags |= ACID_PROOF
- ..()
- if(SSradio)
- set_frequency(frequency)
- component_parts = list()
- var/obj/item/circuitboard/logic_gate/LG = new(null)
- LG.set_type(type)
- component_parts += LG
- component_parts += new /obj/item/stack/cable_coil(null, 1)
-
-/obj/machinery/logic_gate/Initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/logic_gate/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
- return
-
-/obj/machinery/logic_gate/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/logic_gate/process()
- handle_logic()
- handle_output() //All output will send for at least one cycle, and will attempt to send every cycle. Hopefully this won't be too taxing.
- return
-
-/obj/machinery/logic_gate/proc/handle_logic()
- return
-
-/obj/machinery/logic_gate/proc/handle_output()
- if(!radio_connection) //can't output without this
- return
-
- if(output_id_tag == null) //Don't output to an undefined id_tag
- return
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = output_id_tag,
- "sigtype" = "logic",
- "state" = output_state,
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
-
-/obj/machinery/logic_gate/receive_signal(datum/signal/signal, receive_method, receive_param)
- if(!signal.data["tag"] || ((signal.data["tag"] != input1_id_tag) && (signal.data["tag"] != input2_id_tag)) || (signal.data["sigtype"] != "logic"))
- //If the signal lacks tag data, the signal's tag data doesn't match either input id tag, or is not a "logic" signal, ignore it since it's not for us
- return
-
- if(signal.data["tag"] == input1_id_tag) //If the signal is for input1
- if(signal.data["state"] == input1_state) //If we already match, ignore the new signal since nothing changes
- return
- if(signal.data["state"] == LOGIC_OFF) //Shut it down and keep it off
- input1_state = LOGIC_OFF
- return
- if(signal.data["state"] == LOGIC_ON) //Turn it on and keep it on
- input1_state = LOGIC_ON
- return
- if(signal.data["state"] == LOGIC_FLICKER) //Turn it on then turn it off
- if(input1_state == LOGIC_ON) //An existing continuous ON state overrides new flicker signals
- return
- input1_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input1_state == LOGIC_FLICKER) //Make sure we didn't get a new continuous signal set while we waited (those take priority)
- input1_state = LOGIC_OFF
- return
-
- //Now, you may be wondering why I included those returns.
- //The answer is "If you link both inputs to the same source, you're an idiot and deserve to have it break", so yeah. Deal with it.
-
- if(mono_input)
- //We only care about input1, so if we didn't receive a signal for that, we're done.
- return
-
- if(signal.data["tag"] == input2_id_tag) //If the signal is for input2 (reaching this point assumes mono_input is not set)
- if(signal.data["state"] == input2_state) //If we already match, ignore the new signal since nothing changes
- return
- if(signal.data["state"] == LOGIC_OFF) //Shut it down and keep it off
- input2_state = LOGIC_OFF
- return
- if(signal.data["state"] == LOGIC_ON) //Turn it on and keep it on
- input2_state = LOGIC_ON
- return
- if(signal.data["state"] == LOGIC_FLICKER) //Turn it on then turn it off
- if(input2_state == LOGIC_ON) //An existing continuous ON state overrides new flicker signals
- return
- input2_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input2_state == LOGIC_FLICKER) //Make sure we didn't get a new continuous signal set while we waited (those take priority)
- input2_state = LOGIC_OFF
- return
-
-/obj/machinery/logic_gate/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- var/input1_state_string
- var/input2_state_string
- var/output_state_string
-
- switch(input1_state)
- if(LOGIC_OFF)
- input1_state_string = "OFF"
- if(LOGIC_ON)
- input1_state_string = "ON"
- if(LOGIC_FLICKER)
- input1_state_string = "FLICKER"
- else
- input1_state_string = "ERROR: UNKNOWN STATE"
-
- switch(input2_state)
- if(LOGIC_OFF)
- input2_state_string = "OFF"
- if(LOGIC_ON)
- input2_state_string = "ON"
- if(LOGIC_FLICKER)
- input2_state_string = "FLICKER"
- else
- input2_state_string = "ERROR: UNKNOWN STATE"
-
- switch(output_state)
- if(LOGIC_OFF)
- output_state_string = "OFF"
- if(LOGIC_ON)
- output_state_string = "ON"
- if(LOGIC_FLICKER)
- output_state_string = "FLICKER"
- else
- output_state_string = "ERROR: UNKNOWN STATE"
- var/menu_contents = {"
-
-
Input: [format_tag("ID Tag","input1_id_tag")]
-
Input State: [input1_state_string]
- "}
- if(!mono_input)
- menu_contents = {"
-
Input 1: [format_tag("ID Tag","input1_id_tag")]
-
Input 1 State: [input1_state_string]
-
Input 2: [format_tag("ID Tag","input2_id_tag")]
-
Input 2 State: [input2_state_string]
- "}
- menu_contents += {"
-
Output: [format_tag("ID Tag","output_id_tag")]
-
Output State: [output_state_string]
-
- "}
- return menu_contents
-
-/obj/machinery/logic_gate/convert/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- update_multitool_menu(user)
-
-/obj/machinery/logic_gate/attackby(obj/item/O, mob/user, params)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interact with it!")
- return 0
- if(istype(O, /obj/item/multitool))
- update_multitool_menu(user)
- return 1
- if(istype(O, /obj/item/screwdriver))
- panel_open = !panel_open
- to_chat(user, "You [panel_open ? "open" : "close"] the access panel.")
- return 1
- if(panel_open && istype(O, /obj/item/crowbar))
- default_deconstruction_crowbar(user, O)
- return 1
- return ..()
-
-//////////////////////////////////////
-// Attack procs //
-//////////////////////////////////////
-
-/obj/machinery/logic_gate/attack_ai(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interface with it!")
- return 0
- add_hiddenprint(user)
- return ui_interact(user)
-
-/obj/machinery/logic_gate/attack_ghost(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't haunt it!")
- return 0
- return ui_interact(user)
-
-/obj/machinery/logic_gate/attack_hand(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interact with it!")
- return 0
- . = ..()
- if(.)
- return 0
- return interact(user)
-
-/obj/machinery/logic_gate/attack_alien(mob/user) //No xeno logic, that's too silly.
- to_chat(user, "The [src] appears to be too complex! You can't comprehend it and back off in fear!")
- return 0
-
-/obj/machinery/logic_gate/attack_animal(mob/user) //No animal logic either.
- to_chat(user, "The [src] appears to be beyond your comprehension! You can't fathom it!")
- return 0
-
-/obj/machinery/logic_gate/attack_slime(mob/user) //No slime logic. Seriously.
- to_chat(user, "The [src] appears to be beyond your gelatinous understanding! You ignore it!")
- return 0
-
-/obj/machinery/logic_gate/emp_act(severity)
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/ex_act(severity)
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/blob_act(obj/structure/blob/B)
- if(!tamperproof)
- return ..()
-
-/obj/machinery/logic_gate/singularity_act()
- if(tamperproof)
- //This is some top-level tamperproofing right here, that's for sure. It can even defy a singularity!
- return 0
- ..()
-
-/obj/machinery/logic_gate/bullet_act()
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/tesla_act(var/power)
- if(tamperproof)
- tesla_zap(src, 3, power) //If we're tamperproof, we'll just bounce the full shock of the tesla zap we got hit by, so it continues on normally without diminishing
- return 0
- ..()
diff --git a/code/modules/logic/mono_input.dm b/code/modules/logic/mono_input.dm
deleted file mode 100644
index 58b76232fa0..00000000000
--- a/code/modules/logic/mono_input.dm
+++ /dev/null
@@ -1,62 +0,0 @@
-
-//////////////////////////////////
-// Mono-Input Gates //
-//////////////////////////////////
-
-//NOT Gate
-/obj/machinery/logic_gate/not
- name = "NOT Gate"
- desc = "Accepts one input and outputs the reverse state."
- icon_state = "logic_not"
- mono_input = 1 //NOT Gates are the simplest logic gate because they only utilize one input.
- output_state = LOGIC_ON //Starts with an active output, since the input will be OFF at start
-/*
- A quick note regarding NOT Gates:
- - Connecting multiple things to the input of a NOT Gate can cause weird behaviour due to updating both when it receives a signal and when it calls process().
- - This means it will attempt to output once for every logic machine connected to its input's own process() call.
- - It will then attempt to output an additional time based on the current state when it comes to its own process() call.
- - For this reason, it is HIGHLY RECOMMENDED that you only connect a single signal source to the input of a NOT Gate to avoid signal spasms.
- - Connecting multiple things to the output of a NOT Gate should not cause this unusual behavior.
-*/
-/obj/machinery/logic_gate/not/handle_logic() //Our output will always be a continuous signal, even with a FLICKER, it just will update the output when the FLICKER ends
- if(input1_state == LOGIC_ON) //Output is OFF while input is ON
- output_state = LOGIC_OFF
- else if(input1_state == LOGIC_FLICKER) //Output is OFF while input is FLICKER, then output returns to ON when input returns to OFF
- output_state = LOGIC_OFF
- spawn(LOGIC_FLICKER_TIME + 1) //Call handle_logic again after this delay (the input should update from the spawn(LOGIC_FLICKER_TIME) in receive_signal() by then)
- handle_logic()
- else //Output is ON while input is OFF
- output_state = LOGIC_ON
- handle_output()
- return
-
-//STATUS Gate
-/obj/machinery/logic_gate/status
- name = "Status Gate"
- desc = "Accepts one input and outputs the same state, showing a colored light based on current state."
- icon_state = "logic_status"
- mono_input = 1 //STATUS Gate doesn't actually perform logic operations, but instead acts as a testing conduit.
-
-/*
- STATUS Gates are largely a diagnostics tool, but I'm sure someone will still make a logic gate rave with them anyways.
- - There is no need to actually connect an output for these to work, they just need an input to sample from.
- - STATUS Gates attempt to update their lights whenever they receive a signal.
-*/
-
-/obj/machinery/logic_gate/status/receive_signal(datum/signal/signal, receive_method, receive_params)
- ..()
- handle_logic() //STATUS Gate calls handle_logic() when it receives a signal to update its light and output_state
-
-/obj/machinery/logic_gate/status/handle_logic()
- output_state = input1_state //Output is equal to input, since it is simply a connection with an attached light
- if(output_state == LOGIC_OFF) //Red light when OFF
- set_light(2,2,"#ff0000")
- return
- if(output_state == LOGIC_ON) //Green light when ON
- set_light(2,2,"#009933")
- return
- if(output_state == LOGIC_FLICKER) //Orange light when FLICKER, then update after LOGIC_FLICKER_TIME + 1 to reflect the changed state
- set_light(2,2,"#ff9900")
- spawn(LOGIC_FLICKER_TIME + 1)
- handle_logic()
- return
diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm
index 64e7cba86cd..8969463be1d 100644
--- a/code/modules/martial_arts/martial.dm
+++ b/code/modules/martial_arts/martial.dm
@@ -195,6 +195,9 @@
icon = 'icons/obj/library.dmi'
icon_state = "cqcmanual"
+/obj/item/CQC_manual/chef
+ desc = "A small, black manual. Written on the back it says: Bringing the home advantage with you."
+
/obj/item/CQC_manual/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
@@ -227,7 +230,7 @@
/obj/item/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
- if((CLUMSY in user.disabilities) && prob(50))
+ if((CLUMSY in user.mutations) && prob(50))
to_chat(user, "You club yourself over the head with [src].")
user.Weaken(3)
if(ishuman(user))
@@ -275,7 +278,6 @@
return
else
return ..()
- return ..()
/obj/item/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(wielded)
diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm
index a6d6d9e3341..38904d407de 100644
--- a/code/modules/martial_arts/mimejutsu.dm
+++ b/code/modules/martial_arts/mimejutsu.dm
@@ -33,8 +33,8 @@
var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
- D.visible_message("[A] has hit [D] with invisible nuncucks!", \
- "[A] has hit [D] with a with invisible nuncuck!")
+ D.visible_message("[A] has hit [D] with invisible nunchucks!", \
+ "[A] has hit [D] with a with invisible nunchuck!")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.apply_damage(damage, STAMINA, affecting, armor_block)
diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index 454b31b3b74..044b78a04bc 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -82,7 +82,7 @@
new /obj/item/clothing/head/corgi(src)
if(67 to 68)
for(var/i in 1 to rand(4, 7))
- var /newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace)
+ var/newitem = pick(subtypesof(/obj/item/stock_parts))
new newitem(src)
if(69 to 70)
new /obj/item/stack/ore/bluespace_crystal(src, 5)
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index f21978db625..4af48e7050a 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -65,6 +65,8 @@
user.drop_l_hand()
return
var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(!C)
+ C = target.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
var/target_health = target.health
..()
for(var/t in trophies)
@@ -101,6 +103,8 @@
if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK))
return
var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(!C)
+ C = L.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
var/target_health = L.health
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index 44462dedfda..43cce5904e3 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -26,7 +26,7 @@
/obj/item/wormhole_jaunter/proc/get_destinations(mob/user)
var/list/destinations = list()
- for(var/obj/item/radio/beacon/B in world)
+ for(var/obj/item/radio/beacon/B in GLOB.global_radios)
var/turf/T = get_turf(B)
if(is_station_level(T.z))
destinations += B
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index 0b32b6aedde..dbb41229e27 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -109,7 +109,7 @@ GLOBAL_LIST(labor_sheet_values)
if(!alone_in_area(get_area(src), usr))
to_chat(usr, "Prisoners are only allowed to be released while alone.")
else
- switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE))
+ switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE, usr))
if(1)
to_chat(usr, "Shuttle not found.")
if(2)
@@ -121,6 +121,7 @@ GLOBAL_LIST(labor_sheet_values)
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
announcer.autosay(message, "Labor Camp Controller", "Security")
to_chat(usr, "Shuttle received message and will be sent shortly.")
+ usr.create_log(MISC_LOG, "used [src] to call the laborcamp shuttle")
return TRUE
diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
index e9728bc7901..21bc247b0df 100644
--- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm
+++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
@@ -81,7 +81,7 @@
var/mob/dead/observer/current_spirits = list()
for(var/mob/dead/observer/O in GLOB.player_list)
- if((O.following in contents))
+ if((O.orbiting in contents))
ghost_counter++
O.invisibility = 0
current_spirits |= O
@@ -97,13 +97,13 @@
force = 0
var/ghost_counter = ghost_check()
- force = Clamp((ghost_counter * 4), 0, 75)
+ force = clamp((ghost_counter * 4), 0, 75)
user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!")
..()
/obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
var/ghost_counter = ghost_check()
- final_block_chance += Clamp((ghost_counter * 5), 0, 75)
+ final_block_chance += clamp((ghost_counter * 5), 0, 75)
owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!")
return ..()
@@ -120,18 +120,13 @@
return
var/mob/living/carbon/human/H = user
- var/random = rand(1,3)
+ var/random = rand(1,2)
switch(random)
if(1)
to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.")
H.set_species(/datum/species/skeleton)
if(2)
- to_chat(user, "Power courses through you! You can now shift your form at will.")
- if(user.mind)
- var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
- user.mind.AddSpell(D)
- if(3)
to_chat(user, "You feel like you could walk straight through lava now.")
H.weather_immunities |= "lava"
diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
index fa7791edb9e..4ee2c76a419 100644
--- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm
+++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
@@ -82,7 +82,7 @@
B.mineEffect(L)
for(var/mob/living/carbon/human/H in GLOB.player_list)
- if(H == L)
+ if(H.stat == DEAD || H == L)
continue
to_chat(H, "You have an overwhelming desire to kill [L]. [L.p_they(TRUE)] [L.p_have()] been marked red! Go kill [L.p_them()]!")
H.put_in_hands(new /obj/item/kitchen/knife/butcher(H))
diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm
index ac4d6a1e551..0bde4d95464 100644
--- a/code/modules/mining/lavaland/loot/colossus_loot.dm
+++ b/code/modules/mining/lavaland/loot/colossus_loot.dm
@@ -306,7 +306,7 @@
if(H.stat == DEAD)
H.set_species(/datum/species/shadow)
H.revive()
- H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal
+ H.mutations |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal
H.grab_ghost(force = TRUE)
/obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans
@@ -458,7 +458,7 @@
if(isliving(A) && holder_animal)
var/mob/living/L = A
L.notransform = 1
- L.disabilities |= MUTE
+ L.mutations |= MUTE
L.status_flags |= GODMODE
L.mind.transfer_to(holder_animal)
var/obj/effect/proc_holder/spell/targeted/exit_possession/P = new /obj/effect/proc_holder/spell/targeted/exit_possession
@@ -468,7 +468,7 @@
/obj/structure/closet/stasis/dump_contents(var/kill = 1)
STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in src)
- L.disabilities &= ~MUTE
+ L.mutations -=MUTE
L.status_flags &= ~GODMODE
L.notransform = 0
if(holder_animal && !QDELETED(holder_animal))
diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm
index a3f6e738380..fc81e6399ae 100644
--- a/code/modules/mining/lavaland/loot/hierophant_loot.dm
+++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm
@@ -93,7 +93,7 @@
blast_range = initial(blast_range)
if(isliving(user))
var/mob/living/L = user
- var/health_percent = L.health / L.maxHealth
+ var/health_percent = max(L.health / L.maxHealth, 0) // Don't go negative
chaser_cooldown += round(health_percent * 20) //two tenths of a second for each missing 10% of health
cooldown_time += round(health_percent * 10) //one tenth of a second for each missing 10% of health
chaser_speed = max(chaser_speed + health_percent, 0.5) //one tenth of a second faster for each missing 10% of health
diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm
index f54bc974f7e..0af08e40c74 100644
--- a/code/modules/mining/lavaland/loot/tendril_loot.dm
+++ b/code/modules/mining/lavaland/loot/tendril_loot.dm
@@ -383,7 +383,10 @@
var/mob/living/L = target
if(!L.anchored)
L.visible_message("[L] is snagged by [firer]'s hook!")
+ var/old_density = L.density
+ L.density = FALSE // Ensures the hook does not hit the target multiple times
L.forceMove(get_turf(firer))
+ L.density = old_density
/obj/item/projectile/hook/Destroy()
QDEL_NULL(chain)
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 50cb7d09801..579df861c19 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -98,7 +98,7 @@
/obj/machinery/mineral/processing_unit/Destroy()
CONSOLE = null
QDEL_NULL(files)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
@@ -120,7 +120,7 @@
CONSOLE.updateUsrDialog()
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!materials.has_space(material_amount))
unload_mineral(O)
@@ -132,7 +132,7 @@
/obj/machinery/mineral/processing_unit/proc/get_machine_data()
var/dat = "Smelter control console
"
+ else
+ if(hud_used)
+ hud_used.lingchemdisplay.invisibility = 101
/mob/living/carbon/human/proc/handle_pulse(times_fired)
@@ -1123,4 +1104,4 @@
// Need this in species.
//#undef HUMAN_MAX_OXYLOSS
-//#undef HUMAN_CRIT_MAX_OXYLOSS
\ No newline at end of file
+//#undef HUMAN_CRIT_MAX_OXYLOSS
diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm
index 41c108dadb9..9dcf83f2e9a 100644
--- a/code/modules/mob/living/carbon/human/npcs.dm
+++ b/code/modules/mob/living/carbon/human/npcs.dm
@@ -7,7 +7,7 @@
species_exception = list(/datum/species/monkey)
/mob/living/carbon/human/monkey/punpun/Initialize(mapload)
- ..()
+ . = ..()
name = "Pun Pun"
real_name = name
equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform)
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index b53fa03cebf..01a9990ebd8 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -134,11 +134,9 @@
S.message = "[S.message]"
verb = translator.speech_verb
return list("verb" = verb)
- if(mind)
- span = mind.speech_span
if((COMIC in mutations) \
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
- || GetComponent(/datum/component/jestosterone))
+ || HAS_TRAIT(src, TRAIT_JESTER))
span = "sans"
if(WINGDINGS in mutations)
@@ -151,7 +149,7 @@
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
- if(silent || (disabilities & MUTE))
+ if(silent || (MUTE in mutations))
S.message = ""
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index 6034a22139b..0914852b131 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -53,7 +53,6 @@
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
var/speed_mod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
- var/obj/item/mutanthands
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -84,6 +83,7 @@
var/single_gib_type = /obj/effect/decal/cleanable/blood/gibs
var/remains_type = /obj/effect/decal/remains/human //What sort of remains is left behind when the species dusts
var/base_color //Used when setting species.
+ var/list/inherent_factions
//Used in icon caching.
var/race_key = 0
@@ -272,8 +272,6 @@
if(H.status_flags & GOTTAGOFAST)
. -= 1
- if(H.status_flags & GOTTAGOFAST_METH)
- . -= 1
return .
/datum/species/proc/on_species_gain(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
@@ -285,11 +283,19 @@
H.hud_used.update_locked_slots()
H.ventcrawler = ventcrawler
+ if(inherent_factions)
+ for(var/i in inherent_factions)
+ H.faction += i //Using +=/-= for this in case you also gain the faction from a different source.
+
/datum/species/proc/on_species_loss(mob/living/carbon/human/H)
if(H.butcher_results) //clear it out so we don't butcher a actual human.
H.butcher_results = null
H.ventcrawler = initial(H.ventcrawler)
+ if(inherent_factions)
+ for(var/i in inherent_factions)
+ H.faction -= i
+
/datum/species/proc/updatespeciescolor(mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors.
return
@@ -339,30 +345,17 @@
switch(damagetype)
if(BRUTE)
- H.damageoverlaytemp = 20
damage = damage * brute_mod
+ if(damage)
+ H.damageoverlaytemp = 20
if(organ.receive_damage(damage, 0, sharp, used_weapon))
H.UpdateDamageIcon()
- if(H.LAssailant && ishuman(H.LAssailant)) //superheros still get the comical hit markers
- var/mob/living/carbon/human/A = H.LAssailant
- if(A.mind && A.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts))
- var/list/attack_bubble_recipients = list()
- var/mob/living/user
- for(var/mob/O in viewers(user, src))
- if(O.client && O.has_vision(information_only=TRUE))
- attack_bubble_recipients.Add(O.client)
- spawn(0)
- var/image/dmgIcon = image('icons/effects/hit_blips.dmi', src, "dmg[rand(1,2)]",MOB_LAYER+1)
- dmgIcon.pixel_x = (!H.lying) ? rand(-3,3) : rand(-11,12)
- dmgIcon.pixel_y = (!H.lying) ? rand(-11,9) : rand(-10,1)
- flick_overlay(dmgIcon, attack_bubble_recipients, 9)
-
-
if(BURN)
- H.damageoverlaytemp = 20
damage = damage * burn_mod
+ if(damage)
+ H.damageoverlaytemp = 20
if(organ.receive_damage(0, damage, sharp, used_weapon))
H.UpdateDamageIcon()
@@ -436,6 +429,9 @@
else
target.LAssailant = user
+ target.lastattacker = user.real_name
+ target.lastattackerckey = user.ckey
+
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
damage += attack.damage
if(!damage)
@@ -609,13 +605,6 @@
if(!H.has_organ_for_slot(slot))
return FALSE
- if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit))
- if(FAT in H.mutations)
- if(!(I.flags_size & ONESIZEFITSALL))
- if(!disable_warning)
- to_chat(H, "You're too fat to wear the [I].")
- return FALSE
-
switch(slot)
if(slot_l_hand)
return !H.l_hand && !H.incapacitated()
@@ -754,105 +743,8 @@
return FALSE //Unsupported slot
-/datum/species/proc/get_perceived_trauma(mob/living/carbon/human/H)
- return min(H.health, H.maxHealth - H.getStaminaLoss())
-
-/datum/species/proc/handle_hud_icons(mob/living/carbon/human/H)
- if(!H.client)
- return
- handle_hud_icons_health(H)
- H.handle_hud_icons_health_overlay()
- handle_hud_icons_nutrition(H)
-
-/datum/species/proc/handle_hud_icons_health(mob/living/carbon/H)
- if(!H.client)
- return
- handle_hud_icons_health_side(H)
- handle_hud_icons_health_doll(H)
-
-/datum/species/proc/handle_hud_icons_health_side(mob/living/carbon/human/H)
- if(H.healths)
- if(H.stat == DEAD || (H.status_flags & FAKEDEATH))
- H.healths.icon_state = "health7"
- else
- switch(H.hal_screwyhud)
- if(SCREWYHUD_CRIT) H.healths.icon_state = "health6"
- if(SCREWYHUD_DEAD) H.healths.icon_state = "health7"
- if(SCREWYHUD_HEALTHY) H.healths.icon_state = "health0"
- else
- switch(get_perceived_trauma(H))
- if(100 to INFINITY) H.healths.icon_state = "health0"
- if(80 to 100) H.healths.icon_state = "health1"
- if(60 to 80) H.healths.icon_state = "health2"
- if(40 to 60) H.healths.icon_state = "health3"
- if(20 to 40) H.healths.icon_state = "health4"
- if(0 to 20) H.healths.icon_state = "health5"
- else H.healths.icon_state = "health6"
-
-/datum/species/proc/handle_hud_icons_health_doll(mob/living/carbon/human/H)
- if(H.healthdoll)
- if(H.stat == DEAD || (H.status_flags & FAKEDEATH))
- H.healthdoll.icon_state = "healthdoll_DEAD"
- if(H.healthdoll.overlays.len)
- H.healthdoll.overlays.Cut()
- else
- var/list/new_overlays = list()
- var/list/cached_overlays = H.healthdoll.cached_healthdoll_overlays
- // Use the dead health doll as the base, since we have proper "healthy" overlays now
- H.healthdoll.icon_state = "healthdoll_DEAD"
- for(var/obj/item/organ/external/O in H.bodyparts)
- var/damage = O.burn_dam + O.brute_dam
- var/comparison = (O.max_damage/5)
- var/icon_num = 0
- if(damage)
- icon_num = 1
- if(damage > (comparison))
- icon_num = 2
- if(damage > (comparison*2))
- icon_num = 3
- if(damage > (comparison*3))
- icon_num = 4
- if(damage > (comparison*4))
- icon_num = 5
- new_overlays += "[O.limb_name][icon_num]"
- H.healthdoll.overlays += (new_overlays - cached_overlays)
- H.healthdoll.overlays -= (cached_overlays - new_overlays)
- H.healthdoll.cached_healthdoll_overlays = new_overlays
-
-/datum/species/proc/handle_hud_icons_nutrition(mob/living/carbon/human/H)
- if(NO_HUNGER in species_traits)
- return FALSE
- if(H.mind && H.mind.vampire && (H.mind in SSticker.mode.vampires)) //Vampires
- switch(H.nutrition)
- if(NUTRITION_LEVEL_FULL to INFINITY)
- H.throw_alert("nutrition", /obj/screen/alert/fat/vampire)
- if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
- H.throw_alert("nutrition", /obj/screen/alert/full/vampire)
- if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
- H.throw_alert("nutrition", /obj/screen/alert/well_fed/vampire)
- if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
- H.throw_alert("nutrition", /obj/screen/alert/fed/vampire)
- if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
- H.throw_alert("nutrition", /obj/screen/alert/hungry/vampire)
- else
- H.throw_alert("nutrition", /obj/screen/alert/starving/vampire)
- return 1
-
- else ///Any other non-vampires
- switch(H.nutrition)
- if(NUTRITION_LEVEL_FULL to INFINITY)
- H.throw_alert("nutrition", /obj/screen/alert/fat)
- if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
- H.throw_alert("nutrition", /obj/screen/alert/full)
- if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
- H.throw_alert("nutrition", /obj/screen/alert/well_fed)
- if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
- H.throw_alert("nutrition", /obj/screen/alert/fed)
- if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
- H.throw_alert("nutrition", /obj/screen/alert/hungry)
- else
- H.throw_alert("nutrition", /obj/screen/alert/starving)
- return 1
+/datum/species/proc/update_health_hud(mob/living/carbon/human/H)
+ return FALSE
/*
Returns the path corresponding to the corresponding organ
@@ -963,7 +855,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
-/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H)
/proc/get_random_species(species_name = FALSE) // Returns a random non black-listed or hazardous species, either as a string or datum
var/static/list/random_species = list()
diff --git a/code/modules/mob/living/carbon/human/species/diona.dm b/code/modules/mob/living/carbon/human/species/diona.dm
index 22edf961270..a8639a1a948 100644
--- a/code/modules/mob/living/carbon/human/species/diona.dm
+++ b/code/modules/mob/living/carbon/human/species/diona.dm
@@ -108,13 +108,4 @@
/datum/species/diona/pod //Same name and everything; we want the same limitations on them; we just want their regeneration to kick in at all times and them to have special factions
pod = TRUE
-
-/datum/species/diona/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
- . = ..()
- C.faction |= "plants"
- C.faction |= "vines"
-
-/datum/species/diona/pod/on_species_loss(mob/living/carbon/C)
- . = ..()
- C.faction -= "plants"
- C.faction -= "vines"
+ inherent_factions = list("plants", "vines")
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index 157995e9549..7ff32e38644 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -474,7 +474,7 @@
if(P.is_reflectable)
H.visible_message("The [P.name] gets reflected by [H]'s glass skin!", \
"The [P.name] gets reflected by [H]'s glass skin!")
-
+
P.reflect_back(H)
return FALSE
@@ -534,7 +534,7 @@
if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP)
reactive_teleport(H)
-/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_teleport + teleport_cooldown && user != H)
reactive_teleport(H)
@@ -636,12 +636,11 @@
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
- H.AddComponent(/datum/component/waddling)
+ H.AddElement(/datum/element/waddling)
/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C)
. = ..()
- GET_COMPONENT_FROM(waddling, /datum/component/waddling, C)
- waddling.Destroy()
+ C.RemoveElement(/datum/element/waddling)
/datum/species/golem/bananium/get_random_name()
var/clown_name = pick(GLOB.clown_names)
@@ -654,7 +653,7 @@
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
-/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown && user != H)
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm
index 720a13a7d55..790a7f75d3f 100644
--- a/code/modules/mob/living/carbon/human/species/grey.dm
+++ b/code/modules/mob/living/carbon/human/species/grey.dm
@@ -21,7 +21,7 @@
default_genes = list(REMOTE_TALK)
- species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT, CAN_WINGDINGS)
+ species_traits = list(LIPS, IS_WHITELISTED, CAN_WINGDINGS)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_BODY_MARKINGS
dietflags = DIET_HERB
diff --git a/code/modules/mob/living/carbon/human/species/human.dm b/code/modules/mob/living/carbon/human/species/human.dm
index 6052e769c23..1d339917ad0 100644
--- a/code/modules/mob/living/carbon/human/species/human.dm
+++ b/code/modules/mob/living/carbon/human/species/human.dm
@@ -5,7 +5,7 @@
deform = 'icons/mob/human_races/r_def_human.dmi'
primitive_form = /datum/species/monkey
language = "Sol Common"
- species_traits = list(LIPS, CAN_BE_FAT)
+ species_traits = list(LIPS)
skinned_type = /obj/item/stack/sheet/animalhide/human
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS
@@ -18,4 +18,4 @@
reagent_tag = PROCESS_ORG
//Has standard darksight of 2.
-
+
diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm
index fdc7c6c4c46..ec37d3c6c9f 100644
--- a/code/modules/mob/living/carbon/human/species/machine.dm
+++ b/code/modules/mob/living/carbon/human/species/machine.dm
@@ -121,7 +121,7 @@
return
if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics!
var/optic_colour = input(H, "Select optic colour", H.m_colours["head"]) as color|null
- if(H.incapacitated())
+ if(H.incapacitated(TRUE, TRUE, TRUE))
to_chat(H, "You were interrupted while changing the colour of your optics.")
return
if(optic_colour)
@@ -149,7 +149,7 @@
var/new_style = input(H, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair
var/new_color = input("Please select hair color.", "Monitor Color", head_organ.hair_colour) as null|color
- if(H.incapacitated())
+ if(H.incapacitated(TRUE, TRUE, TRUE))
to_chat(H, "You were interrupted while changing your monitor display.")
return
diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm
index 6a478c00f55..9c5b51b743b 100644
--- a/code/modules/mob/living/carbon/human/species/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/monkey.dm
@@ -18,6 +18,7 @@
is_small = 1
has_fine_manipulation = 0
ventcrawler = VENTCRAWLER_NUDE
+ dietflags = DIET_OMNI
show_ssd = 0
eyes = "blank_eyes"
death_message = "lets out a faint chimper as it collapses and stops moving..."
diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm
index 7d1d4c26a61..be2a7f44229 100644
--- a/code/modules/mob/living/carbon/human/species/shadow.dm
+++ b/code/modules/mob/living/carbon/human/species/shadow.dm
@@ -5,6 +5,7 @@
icobase = 'icons/mob/human_races/r_shadow.dmi'
deform = 'icons/mob/human_races/r_shadow.dmi'
dangerous_existence = TRUE
+ inherent_factions = list("faithless")
unarmed_type = /datum/unarmed_attack/claws
@@ -38,10 +39,10 @@
/datum/action/innate/shadow/darkvision/Activate()
var/mob/living/carbon/human/H = owner
if(!H.vision_type)
- H.vision_type = new /datum/vision_override/nightvision
+ H.set_sight(/datum/vision_override/nightvision)
to_chat(H, "You adjust your vision to pierce the darkness.")
else
- H.vision_type = null
+ H.set_sight(null)
to_chat(H, "You adjust your vision to recognize the shadows.")
/datum/species/shadow/on_species_gain(mob/living/carbon/human/H)
@@ -49,14 +50,12 @@
if(grant_vision_toggle)
vision_toggle = new
vision_toggle.Grant(H)
- H.faction |= "faithless"
/datum/species/shadow/on_species_loss(mob/living/carbon/human/H)
..()
if(grant_vision_toggle && vision_toggle)
H.vision_type = null
vision_toggle.Remove(H)
- H.faction -= "faithless"
/datum/species/shadow/handle_life(mob/living/carbon/human/H)
var/light_amount = 0
diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm
index 622e0919b45..60f972b69a4 100644
--- a/code/modules/mob/living/carbon/human/species/slime.dm
+++ b/code/modules/mob/living/carbon/human/species/slime.dm
@@ -13,6 +13,7 @@
icobase = 'icons/mob/human_races/r_slime.dmi'
deform = 'icons/mob/human_races/r_slime.dmi'
remains_type = /obj/effect/decal/remains/slime
+ inherent_factions = list("slime")
// More sensitive to the cold
cold_level_1 = 280
@@ -94,7 +95,7 @@
var/obj/item/organ/external/E = H.bodyparts_by_name[organname]
if(istype(E) && E.dna && istype(E.dna.species, /datum/species/slime))
E.sync_colour_to_human(H)
- H.update_hair(0)
+ H.update_hair()
H.update_body()
..()
@@ -198,4 +199,4 @@
#undef SLIMEPERSON_HUNGERCOST
#undef SLIMEPERSON_MINHUNGER
-#undef SLIMEPERSON_REGROWTHDELAY
\ No newline at end of file
+#undef SLIMEPERSON_REGROWTHDELAY
diff --git a/code/modules/mob/living/carbon/human/species/tajaran.dm b/code/modules/mob/living/carbon/human/species/tajaran.dm
index 8a803aa3bd4..903e4a32332 100644
--- a/code/modules/mob/living/carbon/human/species/tajaran.dm
+++ b/code/modules/mob/living/carbon/human/species/tajaran.dm
@@ -24,7 +24,7 @@
primitive_form = /datum/species/monkey/tajaran
- species_traits = list(LIPS, CAN_BE_FAT)
+ species_traits = list(LIPS)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING
dietflags = DIET_OMNI
@@ -56,4 +56,4 @@
"is holding their breath!")
/datum/species/tajaran/handle_death(gibbed, mob/living/carbon/human/H)
- H.stop_tail_wagging(1)
+ H.stop_tail_wagging()
diff --git a/code/modules/mob/living/carbon/human/species/unathi.dm b/code/modules/mob/living/carbon/human/species/unathi.dm
index 61c34ab41d9..d4e9b02cd9b 100644
--- a/code/modules/mob/living/carbon/human/species/unathi.dm
+++ b/code/modules/mob/living/carbon/human/species/unathi.dm
@@ -104,7 +104,7 @@
return
/datum/species/unathi/handle_death(gibbed, mob/living/carbon/human/H)
- H.stop_tail_wagging(1)
+ H.stop_tail_wagging()
/datum/species/unathi/ashwalker
name = "Ash Walker"
diff --git a/code/modules/mob/living/carbon/human/species/vox.dm b/code/modules/mob/living/carbon/human/species/vox.dm
index e803a33f3ec..6ac20e77b9b 100644
--- a/code/modules/mob/living/carbon/human/species/vox.dm
+++ b/code/modules/mob/living/carbon/human/species/vox.dm
@@ -76,7 +76,7 @@
speciesbox = /obj/item/storage/box/survival_vox
/datum/species/vox/handle_death(gibbed, mob/living/carbon/human/H)
- H.stop_tail_wagging(1)
+ H.stop_tail_wagging()
/datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H)
if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime")
diff --git a/code/modules/mob/living/carbon/human/species/vulpkanin.dm b/code/modules/mob/living/carbon/human/species/vulpkanin.dm
index 9a313042d2d..920cd86659d 100644
--- a/code/modules/mob/living/carbon/human/species/vulpkanin.dm
+++ b/code/modules/mob/living/carbon/human/species/vulpkanin.dm
@@ -50,4 +50,4 @@
"is holding their breath!")
/datum/species/vulpkanin/handle_death(gibbed, mob/living/carbon/human/H)
- H.stop_tail_wagging(1)
+ H.stop_tail_wagging()
diff --git a/code/modules/mob/living/carbon/human/species/wryn.dm b/code/modules/mob/living/carbon/human/species/wryn.dm
index 9e02e2e28be..080a67a032b 100644
--- a/code/modules/mob/living/carbon/human/species/wryn.dm
+++ b/code/modules/mob/living/carbon/human/species/wryn.dm
@@ -50,7 +50,7 @@
/datum/species/wryn/handle_death(gibbed, mob/living/carbon/human/H)
- for(var/mob/living/carbon/C in GLOB.living_mob_list)
+ for(var/mob/living/carbon/C in GLOB.alive_mob_list)
if(C.get_int_organ(/obj/item/organ/internal/wryn/hivenode))
to_chat(C, "Your antennae tingle as you are overcome with pain...")
to_chat(C, "It feels like part of you has died.") // This is bullshit
diff --git a/code/modules/mob/living/carbon/human/species/zombies.dm b/code/modules/mob/living/carbon/human/species/zombies.dm
deleted file mode 100644
index 1f1c4d979b7..00000000000
--- a/code/modules/mob/living/carbon/human/species/zombies.dm
+++ /dev/null
@@ -1,102 +0,0 @@
-#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
-
-/datum/species/zombie
- // 1spooky
- name = "High-Functioning Zombie"
- name_plural = "High-Functioning Zombies"
- icobase = 'icons/mob/human_races/r_zombie.dmi'
- deform = 'icons/mob/human_races/r_def_zombie.dmi'
- dies_at_threshold = TRUE
- language = "Zombie"
- species_traits = list(NO_BLOOD, NOZOMBIE, NOTRANSSTING, NO_BREATHE, RADIMMUNE, NO_SCAN)
- var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
- warning_low_pressure = -1
- hazard_low_pressure = -1
- hazard_high_pressure = 999999999
- warning_high_pressure = 999999999
- cold_level_1 = -1
- cold_level_2 = -1
- cold_level_3 = -1
- tox_mod = 0
- flesh_color = "#00FF00" // for green examine text
- bodyflags = HAS_SKIN_COLOR
- dietflags = DIET_CARN
- has_organ = list(
- "heart" = /obj/item/organ/internal/heart,
- "lungs" = /obj/item/organ/internal/lungs,
- "liver" = /obj/item/organ/internal/liver,
- "kidneys" = /obj/item/organ/internal/kidneys,
- "brain" = /obj/item/organ/internal/brain,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes,
- "ears" = /obj/item/organ/internal/ears)
-
-
-/datum/species/zombie/infectious
- name = "Infectious Zombie"
- mutanthands = /obj/item/zombie_hand
- icobase = 'icons/mob/human_races/r_zombie.dmi'
- deform = 'icons/mob/human_races/r_def_zombie.dmi'
- brute_mod = 0.8 // 120 damage to KO a zombie, which kills it
- burn_mod = 0.8
- clone_mod = 0.8
- brain_mod = 0.8
- stamina_mod = 0.8
- speed_mod = 1.6
- default_language = "Zombie"
- var/heal_rate = 1
- var/regen_cooldown = 0
-
-/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H, amount)
- . = min(20, amount)
-
-/datum/species/zombie/infectious/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
- . = ..()
- if(damage)
- regen_cooldown = world.time + REGENERATION_DELAY
-
-/datum/species/zombie/infectious/handle_life(mob/living/carbon/human/H)
- . = ..()
- H.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
-
- //Zombies never actually die, they just fall down until they regenerate enough to rise back up.
- //They must be restrained, beheaded or gibbed to stop being a threat.
- if(regen_cooldown < world.time)
- var/heal_amt = heal_rate
- if(H.InCritical())
- heal_amt *= 2
- H.heal_overall_damage(heal_amt,heal_amt)
- H.adjustToxLoss(-heal_amt)
- if(!H.InCritical() && prob(4))
- playsound(H, pick(spooks), 50, TRUE, 10)
-
-//Congrats you somehow died so hard you stopped being a zombie
-/datum/species/zombie/infectious/handle_death(gibbed, mob/living/carbon/C)
- . = ..()
- var/obj/item/organ/internal/zombie_infection/infection
- infection = C.get_organ_slot("zombie_infection")
- if(infection)
- qdel(infection)
-
-/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
- . = ..()
- // Deal with the source of this zombie corruption
- // Infection organ needs to be handled separately from mutant_organs
- // because it persists through species transitions
- if(mutanthands)
- H.drop_l_hand()
- H.drop_r_hand()
- H.put_in_hands(new mutanthands())
- H.put_in_hands(new mutanthands())
- var/obj/item/organ/internal/zombie_infection/infection
- infection = H.get_organ_slot("zombie_infection")
- if(!infection)
- infection = new()
- infection.insert(H)
-
-/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/human/C, datum/species/old_species)
- QDEL_NULL(C.r_hand)
- QDEL_NULL(C.l_hand)
- return ..()
-
-#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 6139bed100f..1f38e564928 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -1,8 +1,8 @@
/*
Global associative list for caching humanoid icons.
- Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0.
+ Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk hulk skeleton 1 or 0.
TODO: Proper documentation
- icon_key is [species.race_key][g][husk][fat][hulk][skeleton][s_tone]
+ icon_key is [species.race_key][g][husk][hulk][skeleton][s_tone]
*/
GLOBAL_LIST_EMPTY(human_icon_cache)
@@ -77,14 +77,14 @@ There are several things that need to be remembered:
If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call
it manually:
e.g.
- update_inv_head(0)
- update_inv_l_hand(0)
+ update_inv_head()
+ update_inv_l_hand()
update_inv_r_hand() //<---calls update_icons()
or equivillantly:
- update_inv_head(0)
- update_inv_l_hand(0)
- update_inv_r_hand(0)
+ update_inv_head()
+ update_inv_l_hand()
+ update_inv_r_hand()
update_icons()
> If you need to update all overlays you can use regenerate_icons(). it works exactly like update_clothing used to.
@@ -124,7 +124,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
-/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1)
+/mob/living/carbon/human/UpdateDamageIcon()
// first check whether something actually changed about damage appearance
var/damage_appearance = ""
@@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//BASE MOB SPRITE
-/mob/living/carbon/human/proc/update_body(var/update_icons=1, var/rebuild_base=0)
+/mob/living/carbon/human/proc/update_body(rebuild_base = FALSE)
remove_overlay(BODY_LAYER)
remove_overlay(LIMBS_LAYER) // So we don't get the old species' sprite splatted on top of the new one's
remove_overlay(UNDERWEAR_LAYER)
@@ -273,27 +273,27 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[UNDERWEAR_LAYER] = mutable_appearance(underwear_standing, layer = -UNDERWEAR_LAYER)
apply_overlay(UNDERWEAR_LAYER)
- if(lip_style && (LIPS in dna.species.species_traits))
- var/icon/lips = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "lips_[lip_style]_s")
- lips.Blend(lip_color, ICON_ADD)
- standing += mutable_appearance(lips, layer = -BODY_LAYER)
+ if(lip_style && (LIPS in dna.species.species_traits))
+ var/mutable_appearance/lips = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]_s")
+ lips.color = lip_color
+ standing += lips
overlays_standing[BODY_LAYER] = standing
apply_overlay(BODY_LAYER)
//tail
- update_tail_layer(0)
+ update_tail_layer()
update_int_organs()
//head accessory
- update_head_accessory(0)
+ update_head_accessory()
//markings
- update_markings(0)
+ update_markings()
//hair
- update_hair(0)
- update_fhair(0)
+ update_hair()
+ update_fhair()
//MARKINGS OVERLAY
-/mob/living/carbon/human/proc/update_markings(var/update_icons=1)
+/mob/living/carbon/human/proc/update_markings()
//Reset our markings.
remove_overlay(MARKINGS_LAYER)
@@ -325,7 +325,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(MARKINGS_LAYER)
//HEAD ACCESSORY OVERLAY
-/mob/living/carbon/human/proc/update_head_accessory(var/update_icons=1)
+/mob/living/carbon/human/proc/update_head_accessory()
//Reset our head accessory
remove_overlay(HEAD_ACCESSORY_LAYER)
remove_overlay(HEAD_ACC_OVER_LAYER)
@@ -362,7 +362,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//HAIR OVERLAY
-/mob/living/carbon/human/proc/update_hair(var/update_icons=1)
+/mob/living/carbon/human/proc/update_hair()
//Reset our hair
remove_overlay(HAIR_LAYER)
@@ -376,7 +376,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//base icons
var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s")
- if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic())))
+ if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(ismachineperson(src))))
var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style]
if(hair_style && hair_style.species_allowed)
if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics...
@@ -403,7 +403,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//FACIAL HAIR OVERLAY
-/mob/living/carbon/human/proc/update_fhair(var/update_icons=1)
+/mob/living/carbon/human/proc/update_fhair()
//Reset our facial hair
remove_overlay(FHAIR_LAYER)
remove_overlay(FHAIR_OVER_LAYER)
@@ -447,12 +447,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
-/mob/living/carbon/human/update_mutations(var/update_icons=1)
+/mob/living/carbon/human/update_mutations()
remove_overlay(MUTATIONS_LAYER)
- var/fat
- if(FAT in mutations)
- fat = "fat"
-
var/mutable_appearance/standing = mutable_appearance('icons/effects/genetics.dmi', layer = -MUTATIONS_LAYER)
var/add_image = 0
var/g = "m"
@@ -463,7 +459,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
if(!gene.block)
continue
if(gene.is_active(src))
- var/underlay = gene.OnDrawUnderlays(src, g, fat)
+ var/underlay = gene.OnDrawUnderlays(src, g)
if(underlay)
standing.underlays += underlay
add_image = 1
@@ -473,16 +469,16 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
standing.overlays += "lasereyes_s"
add_image = 1
if((COLDRES in mutations) && (HEATRES in mutations))
- standing.underlays -= "cold[fat]_s"
- standing.underlays -= "fire[fat]_s"
- standing.underlays += "coldfire[fat]_s"
+ standing.underlays -= "cold_s"
+ standing.underlays -= "fire_s"
+ standing.underlays += "coldfire_s"
if(add_image)
overlays_standing[MUTATIONS_LAYER] = standing
apply_overlay(MUTATIONS_LAYER)
-/mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1)
+/mob/living/carbon/human/proc/update_mutantrace()
//BS12 EDIT
var/skel = (SKELETON in mutations)
if(skel)
@@ -490,8 +486,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
else
skeleton = null
- update_hair(0)
- update_fhair(0)
+ update_hair()
+ update_fhair()
/mob/living/carbon/human/update_fire()
@@ -505,41 +501,42 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
..()
- if(notransform) return
- update_mutations(0)
- update_body(0, 1) //Update the body and force limb icon regeneration.
- update_hair(0)
- update_head_accessory(0)
- update_fhair(0)
- update_mutantrace(0)
- update_inv_w_uniform(0,0)
- update_inv_wear_id(0)
- update_inv_gloves(0,0)
- update_inv_glasses(0)
- update_inv_ears(0)
- update_inv_shoes(0,0)
- update_inv_s_store(0)
- update_inv_wear_mask(0)
- update_inv_head(0,0)
- update_inv_belt(0)
- update_inv_back(0)
- update_inv_wear_suit(0)
- update_inv_r_hand(0)
- update_inv_l_hand(0)
- update_inv_handcuffed(0)
- update_inv_legcuffed(0)
- update_inv_pockets(0)
- update_inv_wear_pda(0)
- UpdateDamageIcon(0)
+ if(notransform)
+ return
+ update_mutations()
+ update_body(TRUE) //Update the body and force limb icon regeneration.
+ update_hair()
+ update_head_accessory()
+ update_fhair()
+ update_mutantrace()
+ update_inv_w_uniform()
+ update_inv_wear_id()
+ update_inv_gloves()
+ update_inv_glasses()
+ update_inv_ears()
+ update_inv_shoes()
+ update_inv_s_store()
+ update_inv_wear_mask()
+ update_inv_head()
+ update_inv_belt()
+ update_inv_back()
+ update_inv_wear_suit()
+ update_inv_r_hand()
+ update_inv_l_hand()
+ update_inv_handcuffed()
+ update_inv_legcuffed()
+ update_inv_pockets()
+ update_inv_wear_pda()
+ UpdateDamageIcon()
force_update_limbs()
- update_tail_layer(0)
+ update_tail_layer()
overlays.Cut() // Force all overlays to regenerate
update_fire()
update_icons()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
-/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1)
+/mob/living/carbon/human/update_inv_w_uniform()
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_w_uniform]
@@ -557,13 +554,6 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
t_color = icon_state
var/mutable_appearance/standing = mutable_appearance('icons/mob/uniform.dmi', "[t_color]_s", layer = -UNIFORM_LAYER)
- if(FAT in mutations)
- if(w_uniform.flags_size & ONESIZEFITSALL)
- standing.icon = 'icons/mob/uniform_fat.dmi'
- else
- to_chat(src, "You burst out of \the [w_uniform]!")
- unEquip(w_uniform)
- return
if(w_uniform.icon_override)
standing.icon = w_uniform.icon_override
@@ -575,7 +565,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
bloodsies.color = w_uniform.blood_color
standing.overlays += bloodsies
- if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. // oh my god kys whoever made this if statement jfc :gun:
+ if(w_uniform.accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. // oh my god kys whoever made this if statement jfc :gun:
for(var/obj/item/clothing/accessory/A in w_uniform:accessories)
var/tie_color = A.item_color
if(!tie_color)
@@ -604,7 +594,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
thing.plane = initial(thing.plane)
apply_overlay(UNIFORM_LAYER)
-/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1)
+/mob/living/carbon/human/update_inv_wear_id()
remove_overlay(ID_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id]
@@ -620,7 +610,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[ID_LAYER] = mutable_appearance('icons/mob/mob.dmi', "id", layer = -ID_LAYER)
apply_overlay(ID_LAYER)
-/mob/living/carbon/human/update_inv_gloves(var/update_icons=1)
+/mob/living/carbon/human/update_inv_gloves()
remove_overlay(GLOVES_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves]
@@ -657,7 +647,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(GLOVES_LAYER)
-/mob/living/carbon/human/update_inv_glasses(var/update_icons=1)
+/mob/living/carbon/human/update_inv_glasses()
remove_overlay(GLASSES_LAYER)
remove_overlay(GLASSES_OVER_LAYER)
remove_overlay(OVER_MASK_LAYER)
@@ -698,7 +688,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
update_misc_effects()
-/mob/living/carbon/human/update_inv_ears(var/update_icons=1)
+/mob/living/carbon/human/update_inv_ears()
remove_overlay(EARS_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_l_ear]
@@ -746,7 +736,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[EARS_LAYER] = mutable_appearance('icons/mob/ears.dmi', "[t_type]", layer = -EARS_LAYER)
apply_overlay(EARS_LAYER)
-/mob/living/carbon/human/update_inv_shoes(var/update_icons=1)
+/mob/living/carbon/human/update_inv_shoes()
remove_overlay(SHOES_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_shoes]
@@ -782,7 +772,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[SHOES_LAYER] = bloodsies
apply_overlay(SHOES_LAYER)
-/mob/living/carbon/human/update_inv_s_store(var/update_icons=1)
+/mob/living/carbon/human/update_inv_s_store()
remove_overlay(SUIT_STORE_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_s_store]
@@ -803,7 +793,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(SUIT_STORE_LAYER)
-/mob/living/carbon/human/update_inv_head(var/update_icons=1)
+/mob/living/carbon/human/update_inv_head()
..()
remove_overlay(HEAD_LAYER)
if(client && hud_used)
@@ -829,7 +819,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[HEAD_LAYER] = standing
apply_overlay(HEAD_LAYER)
-/mob/living/carbon/human/update_inv_belt(var/update_icons=1)
+/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt]
@@ -855,7 +845,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(BELT_LAYER)
-/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1)
+/mob/living/carbon/human/update_inv_wear_suit()
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit]
@@ -873,13 +863,6 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
standing = mutable_appearance(wear_suit.icon_override, "[wear_suit.icon_state]", layer = -SUIT_LAYER)
else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name])
standing = mutable_appearance(wear_suit.sprite_sheets[dna.species.name], "[wear_suit.icon_state]", layer = -SUIT_LAYER)
- else if(FAT in mutations)
- if(wear_suit.flags_size & ONESIZEFITSALL)
- standing = mutable_appearance('icons/mob/suit_fat.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER)
- else
- to_chat(src, "You burst out of \the [wear_suit]!")
- unEquip(wear_suit)
- return
else
standing = mutable_appearance('icons/mob/suit.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER)
@@ -903,8 +886,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[SUIT_LAYER] = standing
apply_overlay(SUIT_LAYER)
- update_tail_layer(0)
- update_collar(0)
+ update_tail_layer()
+ update_collar()
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
@@ -937,7 +920,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
client.screen += wear_pda
wear_pda.screen_loc = ui_pda
-/mob/living/carbon/human/update_inv_wear_mask(var/update_icons = 1)
+/mob/living/carbon/human/update_inv_wear_mask()
..()
remove_overlay(FACEMASK_LAYER)
if(client && hud_used)
@@ -973,7 +956,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(FACEMASK_LAYER)
-/mob/living/carbon/human/update_inv_back(var/update_icons=1)
+/mob/living/carbon/human/update_inv_back()
..()
remove_overlay(BACK_LAYER)
if(back)
@@ -996,7 +979,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[BACK_LAYER] = standing
apply_overlay(BACK_LAYER)
-/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1)
+/mob/living/carbon/human/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
if(handcuffed)
if(istype(handcuffed, /obj/item/restraints/handcuffs/pinkcuffs))
@@ -1005,7 +988,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[HANDCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "handcuff1", layer = -HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
-/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1)
+/mob/living/carbon/human/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
clear_alert("legcuffed")
if(legcuffed)
@@ -1018,7 +1001,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(LEGCUFF_LAYER)
-/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1)
+/mob/living/carbon/human/update_inv_r_hand()
..()
remove_overlay(R_HAND_LAYER)
if(r_hand)
@@ -1037,7 +1020,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(R_HAND_LAYER)
-/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1)
+/mob/living/carbon/human/update_inv_l_hand()
..()
remove_overlay(L_HAND_LAYER)
if(l_hand)
@@ -1078,7 +1061,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
client.screen += I
-/mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1)
+/mob/living/carbon/human/proc/update_tail_layer()
remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER.
remove_overlay(TAIL_LAYER) /* This will be one of two things:
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
@@ -1153,7 +1136,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(TAIL_LAYER)
apply_overlay(TAIL_UNDERLIMBS_LAYER)
-/mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1)
+/mob/living/carbon/human/proc/start_tail_wagging()
remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER.
remove_overlay(TAIL_LAYER) /* This will be one of two things:
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
@@ -1229,10 +1212,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(TAIL_LAYER)
apply_overlay(TAIL_UNDERLIMBS_LAYER)
-/mob/living/carbon/human/proc/stop_tail_wagging(var/update_icons=1)
+/mob/living/carbon/human/proc/stop_tail_wagging()
remove_overlay(TAIL_UNDERLIMBS_LAYER)
remove_overlay(TAIL_LAYER)
- update_tail_layer(update_icons) //just trigger a full update for normal stationary sprites
+ update_tail_layer() //just trigger a full update for normal stationary sprites
/mob/living/carbon/human/proc/update_int_organs()
remove_overlay(INTORGAN_LAYER)
@@ -1254,7 +1237,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//Adds a collar overlay above the helmet layer if the suit has one
// Suit needs an identically named sprite in icons/mob/collar.dmi
// For suits with sprite_sheets, an identically named sprite needs to exist in a file like this icons/mob/species/[species_name_here]/collar.dmi.
-/mob/living/carbon/human/proc/update_collar(var/update_icons=1)
+/mob/living/carbon/human/proc/update_collar()
remove_overlay(COLLAR_LAYER)
var/icon/C = new('icons/mob/collar.dmi')
var/mutable_appearance/standing = null
@@ -1290,20 +1273,17 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
apply_overlay(MISC_LAYER)
-/mob/living/carbon/human/admin_Freeze(client/admin, skip_overlays = TRUE)
- . = ..()
- overlays_standing[FROZEN_LAYER] = mutable_appearance(frozen, layer = -FROZEN_LAYER)
- apply_overlay(FROZEN_LAYER)
-
-/mob/living/carbon/human/admin_unFreeze(client/admin, skip_overlays = TRUE)
- . = ..()
- remove_overlay(FROZEN_LAYER)
-
+/mob/living/carbon/human/admin_Freeze(client/admin, skip_overlays = TRUE, mech = null)
+ if(..())
+ overlays_standing[FROZEN_LAYER] = mutable_appearance(frozen, layer = -FROZEN_LAYER)
+ apply_overlay(FROZEN_LAYER)
+ else
+ remove_overlay(FROZEN_LAYER)
/mob/living/carbon/human/proc/force_update_limbs()
for(var/obj/item/organ/external/O in bodyparts)
O.sync_colour_to_human(src)
- update_body(0)
+ update_body()
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
var/list/out = new
@@ -1316,7 +1296,6 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
/mob/living/carbon/human/proc/generate_icon_render_key()
var/husk = (HUSK in mutations)
- var/fat = (FAT in mutations)
var/hulk = (HULK in mutations)
var/skeleton = (SKELETON in mutations)
@@ -1349,4 +1328,4 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
if(part.s_tone)
. += "[part.s_tone]"
- . = "[.][!!husk][!!fat][!!hulk][!!skeleton]"
+ . = "[.][!!husk][!!hulk][!!skeleton]"
diff --git a/code/modules/mob/living/carbon/human/update_stat.dm b/code/modules/mob/living/carbon/human/update_stat.dm
index 14c87e13722..d5d1801e1a7 100644
--- a/code/modules/mob/living/carbon/human/update_stat.dm
+++ b/code/modules/mob/living/carbon/human/update_stat.dm
@@ -12,7 +12,7 @@
/mob/living/carbon/human/update_nearsighted_effects()
var/obj/item/clothing/glasses/G = glasses
- if((disabilities & NEARSIGHTED) && (!istype(G) || !G.prescription))
+ if((NEARSIGHTED in mutations) && (!istype(G) || !G.prescription))
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("nearsighted")
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 832260d3090..c11eaca5293 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,24 +1,39 @@
/mob/living/carbon/Life(seconds, times_fired)
set invisibility = 0
- set background = BACKGROUND_ENABLED
if(notransform)
return
- if(!loc)
+
+ if(damageoverlaytemp)
+ damageoverlaytemp = 0
+ update_damage_hud()
+
+ if(stat != DEAD)
+ handle_organs()
+
+ //stuff in the stomach
+ if(LAZYLEN(stomach_contents))
+ handle_stomach(times_fired)
+
+ . = ..()
+
+ if(QDELETED(src))
return
- if(..())
- . = 1
+ if(.) //not dead
handle_blood()
- for(var/obj/item/organ/internal/O in internal_organs)
- O.on_life()
- handle_changeling()
+ if(LAZYLEN(processing_patches))
+ handle_patches()
+ if(mind)
+ handle_changeling()
handle_wetness(times_fired)
// Increase germ_level regularly
- if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
- germ_level++
+ handle_germs()
+
+ if(stat != DEAD)
+ return TRUE
///////////////
@@ -111,7 +126,7 @@
var/O2_partialpressure = (breath.oxygen/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath.toxins/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
-
+ var/SA_partialpressure = (breath.sleeping_agent/breath.total_moles())*breath_pressure
//OXYGEN
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
@@ -151,22 +166,20 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath.toxins/safe_tox_max) * 10
- adjustToxLoss(Clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
+ adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
//TRACE GASES
- if(breath.trace_gases.len)
- for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
- var/SA_partialpressure = (SA.moles/breath.total_moles())*breath_pressure
- if(SA_partialpressure > SA_para_min)
- Paralyse(3)
- if(SA_partialpressure > SA_sleep_min)
- AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
- else if(SA_partialpressure > 0.01)
- if(prob(20))
- emote(pick("giggle","laugh"))
+ if(breath.sleeping_agent)
+ if(SA_partialpressure > SA_para_min)
+ Paralyse(3)
+ if(SA_partialpressure > SA_sleep_min)
+ AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
+ else if(SA_partialpressure > 0.01)
+ if(prob(20))
+ emote(pick("giggle","laugh"))
//BREATH TEMPERATURE
handle_breath_temperature(breath)
@@ -191,6 +204,11 @@
else
update_action_buttons_icon()
+/mob/living/carbon/proc/handle_organs()
+ for(var/thing in internal_organs)
+ var/obj/item/organ/internal/O = thing
+ O.on_life()
+
/mob/living/carbon/handle_diseases()
for(var/thing in viruses)
var/datum/disease/D = thing
@@ -229,26 +247,26 @@
adjustToxLoss(3)
updatehealth("handle mutations and radiation(75-100)")
- radiation = Clamp(radiation, 0, 100)
+ radiation = clamp(radiation, 0, 100)
/mob/living/carbon/handle_chemicals_in_body()
- if(reagents)
- reagents.metabolize(src)
+ reagents.metabolize(src)
/mob/living/carbon/proc/handle_wetness(times_fired)
if(times_fired % 20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
-/mob/living/carbon/handle_stomach(times_fired)
- for(var/mob/living/M in stomach_contents)
+/mob/living/carbon/proc/handle_stomach(times_fired)
+ for(var/thing in stomach_contents)
+ var/mob/living/M = thing
if(M.loc != src)
- stomach_contents.Remove(M)
+ LAZYREMOVE(stomach_contents, M)
continue
if(stat != DEAD)
if(M.stat == DEAD)
- stomach_contents.Remove(M)
+ LAZYREMOVE(stomach_contents, M)
qdel(M)
continue
if(times_fired % 3 == 1)
@@ -261,7 +279,9 @@
if(stam_regen_start_time <= world.time)
if(stam_paralyzed)
update_stamina()
- setStaminaLoss(0, FALSE)
+ if(staminaloss)
+ setStaminaLoss(0, FALSE)
+ update_health_hud()
var/restingpwr = 1 + 4 * resting
@@ -319,8 +339,17 @@
AdjustHallucinate(-2)
+ // Keep SSD people asleep
+ if(player_logged)
+ Sleeping(2)
+
/mob/living/carbon/handle_sleeping()
if(..())
+ if(mind?.vampire)
+ if(istype(loc, /obj/structure/closet/coffin))
+ adjustBruteLoss(-1, FALSE)
+ adjustFireLoss(-1, FALSE)
+ adjustToxLoss(-1)
handle_dreams()
adjustStaminaLoss(-10)
var/comfort = 1
@@ -336,44 +365,42 @@
comfort += 1 //Aren't naps SO much better when drunk?
AdjustDrunk(-0.2*comfort) //reduce drunkenness while sleeping.
if(comfort > 1 && prob(3))//You don't heal if you're just sleeping on the floor without a blanket.
- adjustBruteLoss(-1*comfort)
- adjustFireLoss(-1*comfort)
+ adjustBruteLoss(-1 * comfort, FALSE)
+ adjustFireLoss(-1 * comfort)
if(prob(10) && health && hal_screwyhud != SCREWYHUD_CRIT)
emote("snore")
- // Keep SSD people asleep
- if(player_logged)
- Sleeping(2)
+
return sleeping
-/mob/living/carbon/handle_hud_icons()
- return
-
-/mob/living/carbon/handle_hud_icons_health()
+/mob/living/carbon/update_health_hud(shown_health_amount)
if(!client)
return
if(healths)
if(stat != DEAD)
- switch(health)
- if(100 to INFINITY)
- healths.icon_state = "health0"
- if(80 to 100)
- healths.icon_state = "health1"
- if(60 to 80)
- healths.icon_state = "health2"
- if(40 to 60)
- healths.icon_state = "health3"
- if(20 to 40)
- healths.icon_state = "health4"
- if(0 to 20)
- healths.icon_state = "health5"
- else
- healths.icon_state = "health6"
+ . = TRUE
+ if(shown_health_amount == null)
+ shown_health_amount = health
+ if(shown_health_amount >= maxHealth)
+ healths.icon_state = "health0"
+ else if(shown_health_amount > maxHealth * 0.8)
+ healths.icon_state = "health1"
+ else if(shown_health_amount > maxHealth * 0.6)
+ healths.icon_state = "health2"
+ else if(shown_health_amount > maxHealth * 0.4)
+ healths.icon_state = "health3"
+ else if(shown_health_amount > maxHealth * 0.2)
+ healths.icon_state = "health4"
+ else if(shown_health_amount > 0)
+ healths.icon_state = "health5"
+ else
+ healths.icon_state = "health6"
else
healths.icon_state = "health7"
- handle_hud_icons_health_overlay()
-/mob/living/carbon/proc/handle_hud_icons_health_overlay()
+/mob/living/carbon/update_damage_hud()
+ if(!client)
+ return
if(stat == UNCONSCIOUS && health <= HEALTH_THRESHOLD_CRIT)
if(check_death_method())
var/severity = 0
@@ -438,3 +465,25 @@
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
+
+/mob/living/carbon/proc/handle_patches()
+ var/multiple_patch_multiplier = processing_patches.len > 1 ? (processing_patches.len * 1.5) : 1
+ var/applied_amount = 0.35 * multiple_patch_multiplier
+
+ for(var/patch in processing_patches)
+ var/obj/item/reagent_containers/food/pill/patch/P = patch
+
+ if(P.reagents && P.reagents.total_volume)
+ var/fractional_applied_amount = applied_amount / P.reagents.total_volume
+ P.reagents.reaction(src, REAGENT_TOUCH, fractional_applied_amount, P.needs_to_apply_reagents)
+ P.needs_to_apply_reagents = FALSE
+ P.reagents.trans_to(src, applied_amount * 0.5)
+ P.reagents.remove_any(applied_amount * 0.5)
+ else
+ if(!P.reagents || P.reagents.total_volume <= 0)
+ LAZYREMOVE(processing_patches, P)
+ qdel(P)
+
+/mob/living/carbon/proc/handle_germs()
+ if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
+ germ_level++
diff --git a/code/modules/mob/living/carbon/update_status.dm b/code/modules/mob/living/carbon/update_status.dm
index b67953c7e69..918968800ce 100644
--- a/code/modules/mob/living/carbon/update_status.dm
+++ b/code/modules/mob/living/carbon/update_status.dm
@@ -2,12 +2,10 @@
if(status_flags & GODMODE)
return
if(stat != DEAD)
-// if(health <= min_health)
if(health <= HEALTH_THRESHOLD_DEAD && check_death_method())
death()
create_debug_log("died of damage, trigger reason: [reason]")
return
-// if(paralysis || sleeping || getOxyLoss() > low_oxy_ko || (status_flags & FAKEDEATH) || health <= crit_health)
if(paralysis || sleeping || (check_death_method() && getOxyLoss() > 50) || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT && check_death_method())
if(stat == CONSCIOUS)
KnockOut()
@@ -16,6 +14,9 @@
if(stat == UNCONSCIOUS)
WakeUp()
create_debug_log("woke up, trigger reason: [reason]")
+ update_damage_hud()
+ update_health_hud()
+ med_hud_set_status()
/mob/living/carbon/update_stamina()
var/stam = getStaminaLoss()
@@ -24,7 +25,6 @@
else if(stam_paralyzed)
stam_paralyzed = FALSE
update_canmove()
- handle_hud_icons_health()
/mob/living/carbon/can_hear()
. = FALSE
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index fa1c392334d..60f186631b7 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -269,6 +269,7 @@
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
+ update_health_hud()
update_stamina()
/mob/living/proc/setStaminaLoss(amount, updating = TRUE)
@@ -284,6 +285,7 @@
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
+ update_health_hud()
update_stamina()
/mob/living/proc/getMaxHealth()
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index 4d8aa1b776b..6af90792355 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -61,10 +61,13 @@
if(mind && suiciding)
mind.suicided = TRUE
+ reset_perspective(null)
clear_fullscreens()
update_sight()
update_action_buttons_icon()
+ update_damage_hud()
+ update_health_hud()
med_hud_set_health()
med_hud_set_status()
if(!gibbed && !QDELETED(src))
@@ -81,8 +84,9 @@
update_canmove()
timeofdeath = world.time
+ create_log(ATTACK_LOG, "died[gibbed ? " (Gibbed)": ""]")
- GLOB.living_mob_list -= src
+ GLOB.alive_mob_list -= src
GLOB.dead_mob_list += src
if(mind)
mind.store_memory("Time of death: [station_time_timestamp("hh:mm:ss", timeofdeath)]", 0)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 5ab604e5b3e..3062ef461f9 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -1,12 +1,10 @@
-/mob/living/Life(seconds, times_fired)
+/mob/living/proc/Life(seconds, times_fired)
+ set waitfor = FALSE
set invisibility = 0
- set background = BACKGROUND_ENABLED
- if(notransform)
- return FALSE
- if(!loc)
- return FALSE
- var/datum/gas_mixture/environment = loc.return_air()
+ if(flying) //TODO: Better floating
+ animate(src, pixel_y = pixel_y + 5 , time = 10, loop = 1, easing = SINE_EASING)
+ animate(pixel_y = pixel_y - 5, time = 10, loop = 1, easing = SINE_EASING)
if(client || registered_z) // This is a temporary error tracker to make sure we've caught everything
var/turf/T = get_turf(src)
@@ -17,51 +15,83 @@
else if (!client && registered_z)
log_game("Z-TRACKING: [src] of type [src.type] has a Z-registration despite not having a client.")
update_z(null)
+
+ if(notransform)
+ return FALSE
+ if(!loc)
+ return FALSE
+
if(stat != DEAD)
//Chemicals in the body
- handle_chemicals_in_body()
+ if(reagents)
+ handle_chemicals_in_body()
+ if(QDELETED(src)) // some chems can gib mobs
+ return
+
+ if(stat != DEAD)
//Mutations and radiation
handle_mutations_and_radiation()
+ if(stat != DEAD)
//Breathing, if applicable
handle_breathing(times_fired)
+ if(stat != DEAD)
//Random events (vomiting etc)
handle_random_events()
- . = 1
+ if(LAZYLEN(viruses))
+ handle_diseases()
- handle_diseases()
+ if(QDELETED(src)) // diseases can qdel the mob via transformations
+ return
//Heart Attack, if applicable
if(stat != DEAD)
handle_heartattack()
//Handle temperature/pressure differences between body and environment
+ var/datum/gas_mixture/environment = loc.return_air()
if(environment)
handle_environment(environment)
handle_fire()
- //stuff in the stomach
- handle_stomach(times_fired)
-
update_gravity(mob_has_gravity())
- update_pulling()
+ if(pulling)
+ update_pulling()
for(var/obj/item/grab/G in src)
G.process()
- if(handle_regular_status_updates()) // Status & health update, are we dead or alive etc.
+ if(stat != DEAD)
+ handle_critical_condition()
+
+ if(stat != DEAD) // Status & health update, are we dead or alive etc.
handle_disabilities() // eye, ear, brain damages
+
+ if(stat != DEAD)
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
- if(client)
- handle_regular_hud_updates()
+ if(stat != DEAD)
+ if(forced_look)
+ if(!isnum(forced_look))
+ var/atom/A = locateUID(forced_look)
+ if(istype(A))
+ var/view = client ? client.view : world.view
+ if(get_dist(src, A) > view || !(src in viewers(view, A)))
+ forced_look = null
+ to_chat(src, "Your direction target has left your view, you are no longer facing anything.")
+ return
+ setDir()
- ..()
+ if(machine)
+ machine.check_eye(src)
+
+ if(stat != DEAD)
+ return TRUE
/mob/living/proc/handle_breathing(times_fired)
return
@@ -71,7 +101,6 @@
/mob/living/proc/handle_mutations_and_radiation()
radiation = 0 //so radiation don't accumulate in simple animals
- return
/mob/living/proc/handle_chemicals_in_body()
return
@@ -85,126 +114,55 @@
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
return
-/mob/living/proc/handle_stomach(times_fired)
- return
-
/mob/living/proc/update_pulling()
- if(pulling)
- if(incapacitated())
- stop_pulling()
-
-//This updates the health and status of the mob (conscious, unconscious, dead)
-/mob/living/proc/handle_regular_status_updates()
- return stat != DEAD
+ if(incapacitated())
+ stop_pulling()
//this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc..
-/mob/living/proc/handle_status_effects()
- handle_stunned()
- handle_weakened()
- handle_stuttering()
- handle_silent()
- handle_drugged()
- handle_slurring()
- handle_paralysed()
- handle_sleeping()
- handle_slowed()
- handle_drunk()
- handle_cultslurring()
-
-
-/mob/living/proc/handle_stunned()
+/mob/living/proc/handle_status_effects() // We check for the status effect in this proc as opposed to the procs below to avoid excessive proc call overhead
if(stunned)
AdjustStunned(-1, updating = 1, force = 1)
- if(!stunned)
- update_icons()
- return stunned
-
-/mob/living/proc/handle_weakened()
if(weakened)
AdjustWeakened(-1, updating = 1, force = 1)
- if(!weakened)
- update_icons()
- return weakened
-
-/mob/living/proc/handle_stuttering()
if(stuttering)
- stuttering = max(stuttering-1, 0)
- return stuttering
-
-/mob/living/proc/handle_silent()
+ stuttering = max(stuttering - 1, 0)
if(silent)
AdjustSilence(-1)
- return silent
-
-/mob/living/proc/handle_drugged()
if(druggy)
AdjustDruggy(-1)
- return druggy
-
-/mob/living/proc/handle_slurring()
if(slurring)
AdjustSlur(-1)
- return slurring
-
-/mob/living/proc/handle_cultslurring()
- if(cultslurring)
- AdjustCultSlur(-1)
- return cultslurring
-
-/mob/living/proc/handle_paralysed()
if(paralysis)
AdjustParalysis(-1, updating = 1, force = 1)
- return paralysis
-
-/mob/living/proc/handle_sleeping()
if(sleeping)
- AdjustSleeping(-1)
- throw_alert("asleep", /obj/screen/alert/asleep)
- else
- clear_alert("asleep")
- return sleeping
-
-/mob/living/proc/handle_slowed()
+ handle_sleeping()
if(slowed)
AdjustSlowed(-1)
- return slowed
+ if(drunk)
+ handle_drunk()
+ if(cultslurring)
+ AdjustCultSlur(-1)
+
+/mob/living/proc/update_damage_hud()
+ return
+
+/mob/living/proc/handle_sleeping()
+ AdjustSleeping(-1)
+ return sleeping
/mob/living/proc/handle_drunk()
- if(drunk)
- AdjustDrunk(-1)
+ AdjustDrunk(-1)
return drunk
/mob/living/proc/handle_disabilities()
//Eyes
- if(disabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own
+ if((BLINDNESS in mutations) || stat) //blindness from disability or unconsciousness doesn't get better on its own
EyeBlind(1)
else if(eye_blind) //blindness, heals slowly over time
AdjustEyeBlind(-1)
else if(eye_blurry) //blurry eyes heal slowly
AdjustEyeBlurry(-1)
-//this handles hud updates. Calls update_vision() and handle_hud_icons()
-/mob/living/proc/handle_regular_hud_updates()
- if(!client) return 0
-
- handle_vision()
- handle_hud_icons()
-
- return 1
-
-/mob/living/proc/handle_vision()
- update_sight()
-
- if(stat == DEAD)
- return
-
- if(machine)
- if(!machine.check_eye(src))
- reset_perspective(null)
- else
- if(!remote_view && !client.adminobs)
- reset_perspective(null)
-
// Gives a mob the vision of being dead
/mob/living/proc/grant_death_vision()
sight |= SEE_TURFS
@@ -215,9 +173,37 @@
see_invisible = SEE_INVISIBLE_OBSERVER
sync_lighting_plane_alpha()
-/mob/living/proc/handle_hud_icons()
- handle_hud_icons_health()
+/mob/living/proc/handle_critical_condition()
return
-/mob/living/proc/handle_hud_icons_health()
- return
+/mob/living/update_health_hud()
+ if(!client)
+ return
+ if(healths)
+ var/severity = 0
+ var/healthpercent = (health / maxHealth) * 100
+ switch(healthpercent)
+ if(100 to INFINITY)
+ healths.icon_state = "health0"
+ if(80 to 100)
+ healths.icon_state = "health1"
+ severity = 1
+ if(60 to 80)
+ healths.icon_state = "health2"
+ severity = 2
+ if(40 to 60)
+ healths.icon_state = "health3"
+ severity = 3
+ if(20 to 40)
+ healths.icon_state = "health4"
+ severity = 4
+ if(1 to 20)
+ healths.icon_state = "health5"
+ severity = 5
+ else
+ healths.icon_state = "health7"
+ severity = 6
+ if(severity > 0)
+ overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
+ else
+ clear_fullscreen("brute")
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 30e10553d3e..f3d23ca3f51 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -3,13 +3,13 @@
var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medhud.add_to_hud(src)
faction += "\ref[src]"
+ GLOB.mob_living_list += src
/mob/living/prepare_huds()
..()
prepare_data_huds()
/mob/living/proc/prepare_data_huds()
- ..()
med_hud_set_health()
med_hud_set_status()
@@ -18,7 +18,7 @@
if(ranged_ability)
ranged_ability.remove_ranged_ability(src)
remove_from_all_data_huds()
-
+ GLOB.mob_living_list -= src
if(LAZYLEN(status_effects))
for(var/s in status_effects)
var/datum/status_effect/S = s
@@ -286,8 +286,9 @@
health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
update_stat("updatehealth([reason])")
- handle_hud_icons_health()
med_hud_set_health()
+ med_hud_set_status()
+ update_health_hud()
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
@@ -375,7 +376,7 @@
return 0
// Living mobs use can_inject() to make sure that the mob is not syringe-proof in general.
-/mob/living/proc/can_inject()
+/mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick)
return TRUE
/mob/living/is_injectable(mob/user, allowmobs = TRUE)
@@ -407,6 +408,8 @@
QDEL_LIST(C.reagents.addiction_list)
C.reagents.addiction_threshold_accumulated.Cut()
+ QDEL_LIST(C.processing_patches)
+
// rejuvenate: Called by `revive` to get the mob into a revivable state
// the admin "rejuvenate" command calls `revive`, not this proc.
/mob/living/proc/rejuvenate()
@@ -512,7 +515,7 @@
return
-/mob/living/Move(atom/newloc, direct)
+/mob/living/Move(atom/newloc, direct, movetime)
if(buckled && buckled.loc != newloc) //not updating position
if(!buckled.anchored)
return buckled.Move(newloc, direct)
@@ -545,7 +548,7 @@
var/mob/living/M = pulling
if(M.lying && !M.buckled && (prob(M.getBruteLoss() * 200 / M.maxHealth)))
M.makeTrail(T)
- pulling.Move(T, get_dir(pulling, T)) // the pullee tries to reach our previous position
+ pulling.Move(T, get_dir(pulling, T), movetime) // the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) // the pullee couldn't keep up
stop_pulling()
@@ -679,9 +682,6 @@
*/////////////////////
/mob/living/proc/resist_grab()
var/resisting = 0
- for(var/obj/O in requests)
- qdel(O)
- resisting++
for(var/X in grabbed_by)
var/obj/item/grab/G = X
resisting++
@@ -737,7 +737,8 @@
clear_alert("weightless")
else
throw_alert("weightless", /obj/screen/alert/weightless)
- float(!has_gravity)
+ if(!flying)
+ float(!has_gravity)
/mob/living/proc/float(on)
if(throwing)
@@ -758,7 +759,7 @@
//called when the mob receives a bright flash
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
- if(check_eye_prot() < intensity && (override_blindness_check || !(disabilities & BLIND)))
+ if(check_eye_prot() < intensity && (override_blindness_check || !(BLINDNESS in mutations)))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
return 1
@@ -801,7 +802,7 @@
if(do_mob(src, who, what.put_on_delay))
if(what && Adjacent(who) && !(what.flags & NODROP))
unEquip(what)
- who.equip_to_slot_if_possible(what, where, 0, 1)
+ who.equip_to_slot_if_possible(what, where, FALSE, TRUE)
add_attack_logs(src, who, "Equipped [what]")
/mob/living/singularity_act()
@@ -822,8 +823,7 @@
spawn_dust()
gib()
-/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
- end_pixel_y = get_standard_pixel_y_offset(lying)
+/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!used_item)
used_item = get_active_hand()
..()
@@ -1024,9 +1024,9 @@
if("stat")
if((stat == DEAD) && (var_value < DEAD))//Bringing the dead back to life
GLOB.dead_mob_list -= src
- GLOB.living_mob_list += src
+ GLOB.alive_mob_list += src
if((stat < DEAD) && (var_value == DEAD))//Kill he
- GLOB.living_mob_list -= src
+ GLOB.alive_mob_list -= src
GLOB.dead_mob_list += src
. = ..()
switch(var_name)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 6e4f13d735f..b38f1819524 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -73,16 +73,15 @@
return shock_damage
/mob/living/emp_act(severity)
- var/list/L = src.get_contents()
- for(var/obj/O in L)
- O.emp_act(severity)
..()
+ for(var/obj/O in contents)
+ O.emp_act(severity)
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
- return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
+ return clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
- return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
+ return clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
@@ -176,7 +175,7 @@
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
- fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
+ fire_stacks = clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
@@ -261,8 +260,6 @@
add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL)
var/obj/item/grab/G = new /obj/item/grab(user, src)
- if(buckled)
- to_chat(user, "You cannot grab [src]; [p_they()] [p_are()] buckled in!")
if(!G) //the grab will delete itself in New if src is anchored
return 0
user.put_in_active_hand(G)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 840f30c20ff..e230f7a2b99 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -28,13 +28,11 @@
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
- var/implanting = 0 //Used for the mind-slave implant
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/digestion_ratio = 1 //controls how quickly reagents metabolize; largely governered by species attributes.
- var/bloodcrawl = 0 //0 No blood crawling, 1 blood crawling, 2 blood crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
@@ -61,7 +59,6 @@
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
var/list/emote_log = list() //like say_log but for emotes
- var/list/recent_tastes = list()
var/blood_volume = 0 //how much blood the mob has
hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index eeaed10b9c5..630b2223321 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -61,7 +61,7 @@ proc/get_radio_key_from_channel(var/channel)
return default_language
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
- var/robot = isSynthetic()
+ var/robot = ismachineperson(src)
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
@@ -172,11 +172,18 @@ proc/get_radio_key_from_channel(var/channel)
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
+ // Do this so it gets logged for all types of communication
+ var/log_message = "[message_mode ? "([message_mode])" : ""] '[message]'"
+ create_log(SAY_LOG, log_message)
var/list/used_radios = list()
if(handle_message_mode(message_mode, message_pieces, verb, used_radios))
return 1
+ // Log of what we've said, plain message, no spans or junk
+ // handle_message_mode should have logged this already if it handled it
+ say_log += log_message
+ log_say(log_message, src)
var/list/handle_v = handle_speech_sound()
var/sound/speech_sound = handle_v[1]
@@ -262,22 +269,18 @@ proc/get_radio_key_from_channel(var/channel)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
- spawn(0)
- if(loc && !isturf(loc))
- var/atom/A = loc //Non-turf, let it handle the speech bubble
- A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
- else //Turf, leave speech bubbles to the mob
- speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
+
+ if(loc && !isturf(loc))
+ var/atom/A = loc //Non-turf, let it handle the speech bubble
+ A.speech_bubble("[A.bubble_icon][speech_bubble_test]", A, speech_bubble_recipients)
+ else //Turf, leave speech bubbles to the mob
+ speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
for(var/obj/O in listening_obj)
spawn(0)
if(O) //It's possible that it could be deleted in the meantime.
O.hear_talk(src, message_pieces, verb)
- //Log of what we've said, plain message, no spans or junk
- say_log += message
- create_log(SAY_LOG, message) // TODO after #13047: Include the channel
- log_say(message, src)
return 1
/obj/effect/speech_bubble
@@ -333,7 +336,8 @@ proc/get_radio_key_from_channel(var/channel)
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
S.speaking.broadcast(src, S.message)
return 1
-
+ // Log it here since it skips the default way say handles it
+ create_log(SAY_LOG, "(whisper) '[message]'")
whisper_say(message_pieces)
// for weird circumstances where you're inside an atom that is also you, like pai's
@@ -362,7 +366,6 @@ proc/get_radio_key_from_channel(var/channel)
say_log += "whisper: [message]"
log_whisper(message, src)
- create_log(SAY_LOG, "WHISPER: [message]")
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
@@ -459,10 +462,7 @@ proc/get_radio_key_from_channel(var/channel)
if(M.client)
speech_bubble_recipients.Add(M.client)
- spawn(0)
- var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
- I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
- flick_overlay(I, speech_bubble_recipients, 30)
+ speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
if(watching.len)
var/rendered = "[name] [not_heard]."
@@ -471,7 +471,7 @@ proc/get_radio_key_from_channel(var/channel)
return 1
-/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
- var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
+/mob/living/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
+ var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
- flick_overlay(I, bubble_recipients, 30)
+ INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, bubble_recipients, 30)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index ddc96a7948f..737298e2815 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -63,6 +63,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
//MALFUNCTION
var/datum/module_picker/malf_picker
+ var/datum/action/innate/ai/choose_modules/modules_action
var/list/datum/AI_Module/current_modules = list()
var/can_dominate_mechs = 0
var/shunted = 0 //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead
@@ -243,7 +244,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/proc/show_borg_info()
stat(null, text("Connected cyborgs: [connected_robots.len]"))
- for(var/mob/living/silicon/robot/R in connected_robots)
+ for(var/thing in connected_robots)
+ var/mob/living/silicon/robot/R = thing
var/robot_status = "Nominal"
if(R.stat || !R.client)
robot_status = "OFFLINE"
@@ -251,8 +253,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
robot_status = "DEPOWERED"
// Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
var/area/A = get_area(R)
+ var/area_name = A ? sanitize(A.name) : "Unknown"
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge] / [R.cell.maxcharge]" : "Empty"] | \
- Module: [R.designation] | Loc: [sanitize(A.name)] | Status: [robot_status]"))
+ Module: [R.designation] | Loc: [area_name] | Status: [robot_status]"))
/mob/living/silicon/ai/rename_character(oldname, newname)
if(!..(oldname, newname))
@@ -571,13 +574,13 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
return FALSE
/mob/living/silicon/ai/emp_act(severity)
+ ..()
if(prob(30))
switch(pick(1,2))
if(1)
view_core()
if(2)
ai_call_shuttle()
- ..()
/mob/living/silicon/ai/ex_act(severity)
..()
@@ -849,13 +852,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "Switched to [network] camera network.")
//End of code by Mord_Sith
-
-/mob/living/silicon/ai/proc/choose_modules()
- set category = "Malfunction"
- set name = "Choose Module"
-
- malf_picker.use(src)
-
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
@@ -1026,15 +1022,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
return
-/mob/living/silicon/ai/proc/corereturn()
- set category = "Malfunction"
- set name = "Return to Main Core"
-
- var/obj/machinery/power/apc/apc = loc
- if(!istype(apc))
- to_chat(src, "You are already in your Main Core.")
- return
- apc.malfvacate()
//Toggles the luminosity and applies it by re-entereing the camera.
/mob/living/silicon/ai/proc/toggle_camera_light()
@@ -1242,8 +1229,17 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices.")
to_chat(src, "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds.")
view_core() //A BYOND bug requires you to be viewing your core before your verbs update
- verbs += /mob/living/silicon/ai/proc/choose_modules
malf_picker = new /datum/module_picker
+ modules_action = new(malf_picker)
+ modules_action.Grant(src)
+
+///Removes all malfunction-related /datum/action's from the target AI.
+/mob/living/silicon/ai/proc/remove_malf_abilities()
+ QDEL_NULL(modules_action)
+ for(var/datum/AI_Module/AM in current_modules)
+ for(var/datum/action/A in actions)
+ if(istype(A, initial(AM.power_type)))
+ qdel(A)
/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target)
if(!istype(target))
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 641b1a2af0f..717f9700316 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -34,7 +34,7 @@
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 2
if(istype(loc, /obj/item/aicard))
diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
index 4b124c364c2..03e56a5e26e 100644
--- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
@@ -67,9 +67,6 @@
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
-
- set background = BACKGROUND_ENABLED
-
var/list/newVisibleTurfs = list()
for(var/camera in cameras)
diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm
index 75e8854b45c..e1be5450811 100644
--- a/code/modules/mob/living/silicon/ai/latejoin.dm
+++ b/code/modules/mob/living/silicon/ai/latejoin.dm
@@ -1,15 +1,5 @@
GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
-/hook/roundstart/proc/spawn_empty_ai()
- for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
- if(S.name != "AI")
- continue
- if(locate(/mob/living) in S.loc)
- continue
- GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S))
-
- return 1
-
/mob/living/silicon/ai/verb/wipe_core()
set name = "Wipe Core"
set category = "OOC"
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 8d1555182a2..61151e35c92 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -37,7 +37,8 @@
else
adjustOxyLoss(-1)
- handle_stunned()
+ if(stunned)
+ AdjustStunned(-1, updating = 1, force = 1)
var/area/my_area = get_area(src)
@@ -140,7 +141,6 @@
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
update_stat("updatehealth([reason])")
- diag_hud_set_status()
diag_hud_set_health()
diff --git a/code/modules/mob/living/silicon/ai/logout.dm b/code/modules/mob/living/silicon/ai/logout.dm
index a8060abd15c..d9dac308870 100644
--- a/code/modules/mob/living/silicon/ai/logout.dm
+++ b/code/modules/mob/living/silicon/ai/logout.dm
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/Logout()
..()
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 0
src.view_core()
return
diff --git a/code/modules/mob/living/silicon/ai/update_status.dm b/code/modules/mob/living/silicon/ai/update_status.dm
index fd001956c67..8ee4a825631 100644
--- a/code/modules/mob/living/silicon/ai/update_status.dm
+++ b/code/modules/mob/living/silicon/ai/update_status.dm
@@ -9,7 +9,7 @@
else if(stat == UNCONSCIOUS)
WakeUp()
create_debug_log("woke up, trigger reason: [reason]")
- //diag_hud_set_status()
+ diag_hud_set_status()
/mob/living/silicon/ai/has_vision(information_only = FALSE)
return ..() && !lacks_power()
diff --git a/code/modules/mob/living/silicon/decoy/death.dm b/code/modules/mob/living/silicon/decoy/death.dm
index 9e58001f47b..74db72978e0 100644
--- a/code/modules/mob/living/silicon/decoy/death.dm
+++ b/code/modules/mob/living/silicon/decoy/death.dm
@@ -4,7 +4,7 @@
if(!.)
return FALSE
icon_state = "ai-crash"
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
if(atoms_share_level(O, src))
O.mode = 2
gib()
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index d91b724370b..321362217a1 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -1,22 +1,18 @@
/mob/living/silicon/pai/Life(seconds, times_fired)
. = ..()
- if(.)
- //if(secHUD == 1)
- // process_sec_hud(src, 1)
- ////if(medHUD == 1)
- // process_med_hud(src, 1)
- if(silence_time)
- if(world.timeofday >= silence_time)
- silence_time = null
- to_chat(src, "Communication circuit reinitialized. Speech and messaging functionality restored.")
+ if(QDELETED(src) || stat == DEAD)
+ return
+ if(silence_time)
+ if(world.timeofday >= silence_time)
+ silence_time = null
+ to_chat(src, "Communication circuit reinitialized. Speech and messaging functionality restored.")
- if(cable)
- if(get_dist(src, cable) > 1)
- var/turf/T = get_turf_or_move(loc)
- for(var/mob/M in viewers(T))
- M.show_message("The data cable rapidly retracts back into its spool.", 3, "You hear a click and the sound of wire spooling rapidly.", 2)
- qdel(src.cable)
- cable = null
+ if(cable)
+ if(get_dist(src, cable) > 1)
+ var/turf/T = get_turf_or_move(loc)
+ for(var/mob/M in viewers(T))
+ M.show_message("The data cable rapidly retracts back into its spool.", 3, "You hear a click and the sound of wire spooling rapidly.", 2)
+ QDEL_NULL(cable)
/mob/living/silicon/pai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm
index f52da9942e4..920dff8a8c2 100644
--- a/code/modules/mob/living/silicon/pai/recruit.dm
+++ b/code/modules/mob/living/silicon/pai/recruit.dm
@@ -1,6 +1,6 @@
// Recruiting observers to play as pAIs
-GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI candidates
+GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler for pAI candidates
/datum/paiCandidate
var/name
@@ -10,12 +10,6 @@ GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI cand
var/comments
var/ready = 0
-
-/hook/startup/proc/paiControllerSetup()
- GLOB.paiController = new /datum/paiController()
- return 1
-
-
/datum/paiController
var/list/pai_candidates = list()
var/list/asked = list()
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 3b51048452e..574dcda3230 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -13,19 +13,6 @@ GLOBAL_LIST_INIT(pai_emotions, list(
GLOBAL_LIST_EMPTY(pai_software_by_key)
GLOBAL_LIST_EMPTY(default_pai_software)
-/hook/startup/proc/populate_pai_software_list()
- var/r = 1 // I would use ., but it'd sacrifice runtime detection
- for(var/type in subtypesof(/datum/pai_software))
- var/datum/pai_software/P = new type()
- if(GLOB.pai_software_by_key[P.id])
- var/datum/pai_software/O = GLOB.pai_software_by_key[P.id]
- to_chat(world, "pAI software module [P.name] has the same key as [O.name]!")
- r = 0
- continue
- GLOB.pai_software_by_key[P.id] = P
- if(P.default)
- GLOB.default_pai_software[P.id] = P
- return r
/mob/living/silicon/pai/New()
..()
diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm
index 5bdea06e18e..7161919df7f 100644
--- a/code/modules/mob/living/silicon/pai/software_modules.dm
+++ b/code/modules/mob/living/silicon/pai/software_modules.dm
@@ -382,14 +382,6 @@
return 1
/mob/living/silicon/pai/proc/hackloop()
- var/turf/T = get_turf_or_move(src.loc)
- for(var/mob/living/silicon/ai/AI in GLOB.player_list)
- if(!T || !is_station_contact(T.z))
- break
- if(T.loc)
- to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].")
- else
- to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.")
var/obj/machinery/door/D = cable.machine
if(!istype(D))
hack_aborted = 1
diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm
index 26b5683d1a3..2a1662b064d 100644
--- a/code/modules/mob/living/silicon/robot/component.dm
+++ b/code/modules/mob/living/silicon/robot/component.dm
@@ -227,7 +227,7 @@
throw_speed = 5
throw_range = 10
origin_tech = "magnets=1;biotech=1"
- var/mode = 1;
+ var/mode = 1
/obj/item/robotanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
if(( (CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
@@ -253,7 +253,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "You can't analyze non-robotic things!")
return
-
+
switch(scan_type)
if("robot")
var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
@@ -269,7 +269,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "Localized Damage:")
if(!LAZYLEN(damaged) && !LAZYLEN(missing))
to_chat(user, "\t Components are OK.")
- else
+ else
if(LAZYLEN(damaged))
for(var/datum/robot_component/org in damaged)
user.show_message(text("\t []: [][] - [] - [] - []", \
@@ -282,7 +282,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(LAZYLEN(missing))
for(var/datum/robot_component/org in missing)
user.show_message("\t [capitalize(org.name)]: MISSING")
-
+
if(H.emagged && prob(5))
to_chat(user, "\t ERROR: INTERNAL SYSTEMS COMPROMISED")
@@ -313,7 +313,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(!organ_found)
to_chat(user, "No prosthetics located.")
- if(H.isSynthetic())
+ if(ismachineperson(H))
to_chat(user, "Internal Fluid Level:[H.blood_volume]/[H.max_blood]")
if(H.bleed_rate)
to_chat(user, "Warning:External component leak detected!")
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index 224c706f324..72d9b210712 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -18,7 +18,7 @@
flick("gibbed-r", animation)
robogibs(loc)
- GLOB.living_mob_list -= src
+ GLOB.alive_mob_list -= src
GLOB.dead_mob_list -= src
QDEL_IN(animation, 15)
QDEL_IN(src, 15)
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 48f1acd80fa..91970d030a6 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -6,6 +6,7 @@
icon_state = "repairbot"
maxHealth = 35
health = 35
+ bubble_icon = "machine"
universal_speak = 0
universal_understand = 1
gender = NEUTER
@@ -13,11 +14,14 @@
braintype = "Robot"
lawupdate = 0
density = 0
+ has_camera = FALSE
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
ventcrawler = 2
magpulse = 1
mob_size = MOB_SIZE_SMALL
+ modules_break = FALSE
+
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
var/obj/item/stack/sheet/metal/cyborg/stack_metal = null
@@ -48,7 +52,7 @@
if(radio)
radio.wires.CutWireIndex(RADIO_WIRE_TRANSMIT)
- if(camera && "Robots" in camera.network)
+ if(camera && ("Robots" in camera.network))
camera.network.Add("Engineering")
//They are unable to be upgraded, so let's give them a bit of a better battery.
@@ -79,7 +83,7 @@
scanner.Grant(src)
update_icons()
-/mob/living/silicon/robot/drone/init()
+/mob/living/silicon/robot/drone/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/drone()
connected_ai = null
@@ -142,7 +146,7 @@
user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.", "You swipe your ID card through [src], attempting to reboot it.")
last_reboot = world.time / 10
var/drones = 0
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
if(drones < config.max_maint_drones)
@@ -350,3 +354,20 @@
/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
if(affect_silicon)
return ..()
+
+/mob/living/silicon/robot/drone/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!client && istype(user, /mob/living/silicon/robot/drone))
+ to_chat(user, "You begin decompiling the other drone.")
+ if(!do_after(user, 5 SECONDS, target = loc))
+ to_chat(user, "You need to remain still while decompiling such a large object.")
+ return
+ if(QDELETED(src) || QDELETED(user))
+ return ..()
+ to_chat(user, "You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.")
+ new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
+ C.stored_comms["metal"] += 15
+ C.stored_comms["glass"] += 15
+ C.stored_comms["wood"] += 5
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
index 80d9f4d1ba3..d961d8e1c62 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
@@ -34,7 +34,7 @@
var/dat
dat += "Maintenance Units "
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
dat += " [D.real_name] ([D.stat == 2 ? "INACTIVE" : "ACTIVE"])"
dat += " Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += " Currently located in: [get_area(D)]."
@@ -74,7 +74,7 @@
else if(href_list["ping"])
to_chat(usr, "You issue a maintenance request for all active drones, highlighting [drone_call_area].")
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.client && D.stat == 0)
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index d200bdb075a..a0582c135e4 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -30,29 +30,22 @@
/obj/item/circuitboard,
/obj/item/stack/tile/light,
/obj/item/stack/ore/bluespace_crystal
- )
+ )
//Item currently being held.
- var/obj/item/wrapped = null
-
-/obj/item/gripper/paperwork
- name = "paperwork gripper"
- desc = "A simple grasping tool for clerical work."
-
- can_hold = list(
- /obj/item/clipboard,
- /obj/item/paper,
- /obj/item/card/id
- )
+ var/obj/item/gripped_item = null
/obj/item/gripper/medical
name = "medical gripper"
desc = "A grasping tool used to help patients up once surgery is complete."
can_hold = list()
-/obj/item/gripper/medical/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
+/obj/item/gripper/medical/attack_self(mob/user)
+ return
+
+/obj/item/gripper/medical/afterattack(atom/target, mob/living/user, proximity, params)
var/mob/living/carbon/human/H
- if(!wrapped && proximity && target && ishuman(target))
+ if(!gripped_item && proximity && target && ishuman(target))
H = target
if(H.lying)
H.AdjustSleeping(-5)
@@ -71,98 +64,69 @@
..()
can_hold = typecacheof(can_hold)
-/obj/item/gripper/attack_self(mob/user as mob)
- if(wrapped)
- wrapped.attack_self(user)
-
-/obj/item/gripper/verb/drop_item()
-
+/obj/item/gripper/verb/drop_item_gripped()
set name = "Drop Gripped Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
- drop_item_p()
+ drop_gripped_item()
-// The "p" stands for proc, since I was having annoying weird stuff happening with this in the verb
-// when trying to have default values for arguments and stuff
-/obj/item/gripper/proc/drop_item_p(var/silent = 0)
+/obj/item/gripper/attack_self(mob/user)
+ if(gripped_item)
+ gripped_item.attack_self(user)
+ else
+ to_chat(user, "[src] is empty.")
- if(!wrapped)
- //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
- for(var/obj/item/thing in src.contents)
- thing.forceMove(get_turf(src))
- return
+/obj/item/gripper/proc/drop_gripped_item(silent = FALSE)
+ if(gripped_item)
+ if(!silent)
+ to_chat(loc, "You drop [gripped_item].")
+ gripped_item.forceMove(get_turf(src))
+ gripped_item = null
- if(wrapped.loc != src)
- wrapped = null
- return
-
- if(!silent)
- to_chat(src.loc, "You drop \the [wrapped].")
- wrapped.forceMove(get_turf(src))
- wrapped = null
-
-/obj/item/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
+/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user)
return
-/obj/item/gripper/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
+/// Grippers are snowflakey so this is needed to to prevent forceMoving grippers after `if(!user.drop_item())` checks done in certain attackby's.
+/obj/item/gripper/forceMove(atom/destination)
+ return
+
+/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params)
if(!target || !proximity) //Target is invalid or we are not adjacent.
- return
+ return FALSE
- //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
- if(!wrapped)
- for(var/obj/item/thing in src.contents)
- wrapped = thing
- break
+ if(gripped_item) //Already have an item.
- if(wrapped) //Already have an item.
-
- //Temporary put wrapped into user so target's attackby() checks pass.
- wrapped.forceMove(user)
-
- //Pass the attack on to the target. This might delete/relocate wrapped.
- if(!target.attackby(wrapped, user, params) && target && wrapped)
- // If the attackby didn't resolve or delete the target or wrapped, afterattack
+ //Pass the attack on to the target. This might delete/relocate gripped_item.
+ if(!target.attackby(gripped_item, user, params))
+ // If the attackby didn't resolve or delete the target or gripped_item, afterattack
// (Certain things, such as mountable frames, rely on afterattack)
- wrapped.afterattack(target, user, 1, params)
+ gripped_item?.afterattack(target, user, 1, params)
- //If wrapped did neither get deleted nor put into target, put it back into the gripper.
- if(wrapped && user && (wrapped.loc == user))
- wrapped.forceMove(src)
- else
- wrapped = null
- return
-
- else if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
-
- //...and that the item is not in a container.
- if(!isturf(target.loc))
- return
+ //If gripped_item either didn't get deleted, or it failed to be transfered to its target
+ if(!gripped_item && contents.len)
+ gripped_item = contents[1]
+ return FALSE
+ else if(gripped_item && !contents.len)
+ gripped_item = null
+ else if(istype(target, /obj/item)) //Check that we're not pocketing a mob.
var/obj/item/I = target
-
- //Check if the item is blacklisted.
- var/grab = 0
- if(can_hold.len)
- if(is_type_in_typecache(I, can_hold))
- grab = 1
-
- //We can grab the item, finally.
- if(grab)
- to_chat(user, "You collect \the [I].")
+ if(is_type_in_typecache(I, can_hold)) // Make sure the item is something the gripper can hold
+ to_chat(user, "You collect [I].")
I.forceMove(src)
- wrapped = I
- return
+ gripped_item = I
else
- to_chat(user, "Your gripper cannot hold \the [target].")
+ to_chat(user, "Your gripper cannot hold [target].")
+ return FALSE
else if(istype(target,/obj/machinery/power/apc))
var/obj/machinery/power/apc/A = target
if(A.opened)
if(A.cell)
- wrapped = A.cell
+ gripped_item = A.cell
A.cell.add_fingerprint(user)
A.cell.update_icon()
@@ -173,6 +137,7 @@
A.update_icon()
user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.")
+ return TRUE
//TODO: Matter decompiler.
/obj/item/matter_decompiler
@@ -186,15 +151,13 @@
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
- "wood" = 0,
- "plastic" = 0
+ "wood" = 0
)
/obj/item/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
-/obj/item/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
-
+/obj/item/matter_decompiler/afterattack(atom/target, mob/living/user, proximity, params)
if(!proximity) return //Not adjacent.
//We only want to deal with using this on turfs. Specific items aren't important.
@@ -203,101 +166,11 @@
return
//Used to give the right message.
- var/grabbed_something = 0
+ var/grabbed_something = FALSE
- for(var/mob/M in T)
- if(istype(M,/mob/living/simple_animal/lizard) || istype(M,/mob/living/simple_animal/mouse))
- src.loc.visible_message("[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.","It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.")
- new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
- qdel(M)
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- return
-
- else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
-
- var/mob/living/silicon/robot/drone/D = src.loc
-
- if(!istype(D))
- return
-
- to_chat(D, "You begin decompiling the other drone.")
-
- if(!do_after(D, 50, target = target))
- to_chat(D, "You need to remain still while decompiling such a large object.")
- return
-
- if(!M || !D) return
-
- to_chat(D, "You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.")
-
- qdel(M)
- new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
-
- stored_comms["metal"] += 15
- stored_comms["glass"] += 15
- stored_comms["wood"] += 5
- stored_comms["plastic"] += 5
-
- return
- else
- continue
-
- for(var/obj/W in T)
- //Different classes of items give different commodities.
- if(istype(W,/obj/item/cigbutt))
- stored_comms["plastic"]++
- else if(istype(W,/obj/structure/spider/spiderling))
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- else if(istype(W,/obj/item/light))
- var/obj/item/light/L = W
- if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
- stored_comms["metal"]++
- stored_comms["glass"]++
- else
- continue
- else if(istype(W,/obj/effect/decal/remains/robot))
- stored_comms["metal"]++
- stored_comms["metal"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/trash))
- stored_comms["metal"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
- stored_comms["metal"]++
- stored_comms["metal"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/ammo_casing))
- stored_comms["metal"]++
- else if(istype(W,/obj/item/shard))
- stored_comms["glass"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/reagent_containers/food/snacks/grown))
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["wood"]++
- else if(istype(W,/obj/item/broken_bottle))
- stored_comms["glass"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/light/tube) || istype(W,/obj/item/light/bulb))
- stored_comms["glass"]++
- else
- continue
-
- qdel(W)
- grabbed_something = 1
+ for(var/atom/movable/A in T)
+ if(A.decompile_act(src, user)) // Each decompileable mob or obj needs to have this defined
+ grabbed_something = TRUE
if(grabbed_something)
to_chat(user, "You deploy your decompiler and clear out the contents of \the [T].")
@@ -388,11 +261,5 @@
stack_wood = new /obj/item/stack/sheet/wood(src.module)
stack_wood.amount = 1
stack = stack_wood
- if("plastic")
- if(!stack_plastic)
- stack_plastic = new /obj/item/stack/sheet/plastic(src.module)
- stack_plastic.amount = 1
- stack = stack_plastic
-
stack.amount++
decompiler.stored_comms[type]--
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
index 50463b17bec..023cced9cdb 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
@@ -52,7 +52,7 @@
/obj/machinery/drone_fabricator/proc/count_drones()
var/drones = 0
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
return drones
@@ -142,7 +142,7 @@
if(alert("Are you sure you want to respawn as a drone?", "Are you sure?", "Yes", "No") != "Yes")
return
- for(var/obj/machinery/drone_fabricator/DF in world)
+ for(var/obj/machinery/drone_fabricator/DF in GLOB.machines)
if(DF.stat & NOPOWER || !DF.produce_drones)
continue
diff --git a/code/modules/mob/living/silicon/robot/drone/update_status.dm b/code/modules/mob/living/silicon/robot/drone/update_status.dm
index 80eac952966..d64824b1876 100644
--- a/code/modules/mob/living/silicon/robot/drone/update_status.dm
+++ b/code/modules/mob/living/silicon/robot/drone/update_status.dm
@@ -4,7 +4,7 @@
/mob/living/silicon/robot/drone/update_stat(reason = "none given")
if(status_flags & GODMODE)
return
- if(health <= -35 && stat != DEAD)
+ if(health <= -maxHealth && stat != DEAD)
gib()
create_debug_log("died of damage, trigger reason: [reason]")
return
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 16d9080ef7e..f5b7048c3a8 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -78,6 +78,7 @@
set_actions(O)
else
to_chat(src, "You need to disable a module first!")
+ check_module_damage(FALSE)
update_icons()
/mob/living/silicon/robot/proc/set_actions(obj/item/I)
@@ -115,11 +116,11 @@
return 0
/mob/living/silicon/robot/drop_item()
- var/obj/item/I = get_active_hand()
- if(istype(I, /obj/item/gripper))
- var/obj/item/gripper/G = I
- G.drop_item_p(silent = 1)
- return
+ var/obj/item/gripper/G = get_active_hand()
+ if(istype(G))
+ G.drop_gripped_item(silent = TRUE)
+ return TRUE // The gripper is special because it has a normal item inside that we can drop.
+ return FALSE // All robot inventory items have NODROP, so they should return FALSE.
//Helper procs for cyborg modules on the UI.
//These are hackish but they help clean up code elsewhere.
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index d40e801ba5f..07080e694bf 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -1,23 +1,20 @@
/mob/living/silicon/robot/Life(seconds, times_fired)
set invisibility = 0
- set background = BACKGROUND_ENABLED
-
- if(src.notransform)
+ if(notransform)
return
- //Status updates, death etc.
- clamp_values()
+ . = ..()
- if(..())
+ handle_equipment()
+
+ // if Alive
+ if(.)
+ handle_robot_hud_updates()
handle_robot_cell()
process_locks()
+ update_items()
process_queued_alarms()
-/mob/living/silicon/robot/proc/clamp_values()
- SetStunned(min(stunned, 30))
- SetParalysis(min(paralysis, 30))
- SetWeakened(min(weakened, 20))
- SetSleeping(0)
/mob/living/silicon/robot/proc/handle_robot_cell()
if(stat != DEAD)
@@ -39,7 +36,7 @@
if(is_component_functioning("power cell") && cell.charge)
if(cell.charge <= 100)
uneq_all()
- var/amt = Clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
+ var/amt = clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
cell.use(amt) //Usage table: 1/tick if off/lowest setting, 4 = 4/tick, 6 = 8/tick, 8 = 12/tick, 10 = 16/tick
else
uneq_all()
@@ -47,36 +44,13 @@
update_headlamp()
diag_hud_set_borgcell()
-/mob/living/silicon/robot/handle_regular_status_updates()
-
- . = ..()
-
+/mob/living/silicon/robot/proc/handle_equipment()
if(camera && !scrambledcodes)
if(stat == DEAD || wires.IsCameraCut())
camera.status = 0
else
camera.status = 1
- if(sleeping)
- AdjustSleeping(-1)
-
- if(.) //alive
- if(!istype(src, /mob/living/silicon/robot/drone))
- if(health < 50) //Gradual break down of modules as more damage is sustained
- if(uneq_module(module_state_3))
- to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.")
-
- if(health < 0)
- if(uneq_module(module_state_2))
- to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.")
-
- if(health < -50)
- if(uneq_module(module_state_1))
- to_chat(src, "CRITICAL ERROR: All modules OFFLINE.")
-
- diag_hud_set_health()
- diag_hud_set_status()
-
//update the state of modules and components here
if(stat != CONSCIOUS)
uneq_all()
@@ -86,18 +60,21 @@
else
radio.on = 1
- return 1
-
-/mob/living/silicon/robot/handle_hud_icons()
- update_items()
- update_cell()
+/mob/living/silicon/robot/proc/SetEmagged(new_state)
+ emagged = new_state
+ update_icons()
if(emagged)
throw_alert("hacked", /obj/screen/alert/hacked)
else
clear_alert("hacked")
- ..()
-/mob/living/silicon/robot/handle_hud_icons_health()
+/mob/living/silicon/robot/proc/handle_robot_hud_updates()
+ if(!client)
+ return
+
+ update_cell_hud_icon()
+
+/mob/living/silicon/robot/update_health_hud()
if(healths)
if(stat != DEAD)
if(health >= maxHealth)
@@ -115,19 +92,7 @@
else
healths.icon_state = "health7"
- switch(bodytemperature) //310.055 optimal body temp
- if(335 to INFINITY)
- throw_alert("temp", /obj/screen/alert/hot/robot, 2)
- if(320 to 335)
- throw_alert("temp", /obj/screen/alert/hot/robot, 1)
- if(300 to 320)
- clear_alert("temp")
- if(260 to 300)
- throw_alert("temp", /obj/screen/alert/cold/robot, 1)
- else
- throw_alert("temp", /obj/screen/alert/cold/robot, 2)
-
-/mob/living/silicon/robot/proc/update_cell()
+/mob/living/silicon/robot/proc/update_cell_hud_icon()
if(cell)
var/cellcharge = cell.charge/cell.maxcharge
switch(cellcharge)
@@ -146,7 +111,7 @@
-/mob/living/silicon/robot/proc/update_items()
+/mob/living/silicon/robot/proc/update_items() // What in the Sam hell is this?
if(client)
for(var/obj/I in get_all_slots())
client.screen |= I
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index a8bad5ebc03..faa51a58ec0 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -9,6 +9,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
icon_state = "robot"
maxHealth = 100
health = 100
+ bubble_icon = "robot"
universal_understand = 1
deathgasp_on_death = TRUE
@@ -16,8 +17,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
-//Hud stuff
-
+ //Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
-//3 Modules can be activated at any one time.
+ //3 Modules can be activated at any one time.
var/obj/item/robot_module/module = null
var/module_active = null
var/module_state_1 = null
@@ -57,6 +57,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/is_emaggable = TRUE
var/eye_protection = 0
var/ear_protection = 0
+ var/damage_protection = 0
+ var/emp_protection = FALSE
+ var/xeno_disarm_chance = 85
var/list/force_modules = list()
var/allow_rename = TRUE
@@ -82,11 +85,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/lockcharge //Used when locking down a borg to preserve cell charge
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
+ var/has_camera = TRUE
var/pdahide = 0 //Used to hide the borg from the messenger list
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
var/braintype = "Cyborg"
var/base_icon = ""
- var/crisis = 0
+ var/modules_break = TRUE
var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting.
var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power.
@@ -96,6 +100,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
+ var/default_cell_type = /obj/item/stock_parts/cell/high
var/magpulse = 0
var/ionpulse = 0 // Jetpack-like effect.
var/ionpulse_on = 0 // Jetpack-like effect.
@@ -107,7 +112,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/get_cell()
return cell
-/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0)
+/mob/living/silicon/robot/New(loc, syndie = FALSE, unfinished = FALSE, alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
@@ -129,9 +134,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
radio = new /obj/item/radio/borg(src)
common_radio = radio
- init()
+ init(ai_to_sync_to = ai_to_sync_to)
- if(!scrambledcodes && !camera)
+ if(has_camera && !camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = list("SS13","Robots")
@@ -143,7 +148,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mmi.icon_state = "boris"
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
- cell = new /obj/item/stock_parts/cell/high(src)
+ cell = new default_cell_type(src)
initialize_components()
//if(!unfinished)
@@ -167,14 +172,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scanner = new(src)
scanner.Grant(src)
-/mob/living/silicon/robot/proc/init(var/alien=0)
+/mob/living/silicon/robot/proc/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
make_laws()
additional_law_channels["Binary"] = ":b "
- var/new_ai = select_active_ai_with_fewest_borgs()
- if(new_ai)
+ var/found_ai = ai_to_sync_to
+ if(!found_ai)
+ found_ai = select_active_ai_with_fewest_borgs()
+ if(found_ai)
lawupdate = 1
- connect_to_ai(new_ai)
+ connect_to_ai(found_ai)
else
lawupdate = 0
@@ -234,7 +241,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(custom_name)
return 0
if(!allow_rename)
- to_chat(src, "Rename functionality is not enabled on this unit.");
+ to_chat(src, "Rename functionality is not enabled on this unit.")
return 0
rename_self(braintype, 1)
@@ -287,12 +294,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
- var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
+ var/list/modules = list("Generalist", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
if(islist(force_modules) && force_modules.len)
modules = force_modules.Copy()
- if(GLOB.security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
- to_chat(src, "Crisis mode active. The combat module is now available.")
- modules += "Combat"
if(mmi != null && mmi.alien)
modules = list("Hunter")
modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
@@ -305,9 +309,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
switch(modtype)
- if("Standard")
+ if("Generalist")
module = new /obj/item/robot_module/standard(src)
- module.channels = list("Service" = 1)
+ module.channels = list("Engineering" = 1, "Medical" = 1, "Security" = 1, "Service" = 1)
module_sprites["Basic"] = "robot_old"
module_sprites["Android"] = "droid"
module_sprites["Default"] = "Standard"
@@ -328,7 +332,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if("Miner")
module = new /obj/item/robot_module/miner(src)
module.channels = list("Supply" = 1)
- if(camera && "Robots" in camera.network)
+ if(camera && ("Robots" in camera.network))
camera.network.Add("Mining Outpost")
module_sprites["Basic"] = "Miner_old"
module_sprites["Advanced Droid"] = "droid-miner"
@@ -336,11 +340,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Standard"] = "Standard-Mine"
module_sprites["Noble-DIG"] = "Noble-DIG"
module_sprites["Cricket"] = "Cricket-MINE"
+ module_sprites["Lavaland"] = "lavaland"
if("Medical")
module = new /obj/item/robot_module/medical(src)
module.channels = list("Medical" = 1)
- if(camera && "Robots" in camera.network)
+ if(camera && ("Robots" in camera.network))
camera.network.Add("Medical")
module_sprites["Basic"] = "Medbot"
module_sprites["Surgeon"] = "surgeon"
@@ -352,6 +357,17 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
status_flags &= ~CANPUSH
if("Security")
+ if(!weapons_unlock)
+ var/count_secborgs = 0
+ for(var/mob/living/silicon/robot/R in GLOB.alive_mob_list)
+ if(R && R.stat != DEAD && R.module && istype(R.module, /obj/item/robot_module/security))
+ count_secborgs++
+ var/max_secborgs = 2
+ if(GLOB.security_level == SEC_LEVEL_GREEN)
+ max_secborgs = 1
+ if(count_secborgs >= max_secborgs)
+ to_chat(src, "There are too many Security cyborgs active. Please choose another module.")
+ return
module = new /obj/item/robot_module/security(src)
module.channels = list("Security" = 1)
module_sprites["Basic"] = "secborg"
@@ -366,7 +382,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if("Engineering")
module = new /obj/item/robot_module/engineering(src)
module.channels = list("Engineering" = 1)
- if(camera && "Robots" in camera.network)
+ if(camera && ("Robots" in camera.network))
camera.network.Add("Engineering")
module_sprites["Basic"] = "Engineering"
module_sprites["Antique"] = "engineerrobot"
@@ -386,10 +402,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Noble-CLN"] = "Noble-CLN"
module_sprites["Cricket"] = "Cricket-JANI"
- if("Combat")
- module = new /obj/item/robot_module/combat(src)
+ if("Destroyer") // Rolling Borg
+ module = new /obj/item/robot_module/destroyer(src)
module.channels = list("Security" = 1)
icon_state = "droidcombat"
+ status_flags &= ~CANPUSH
+
+ if("Combat") // Gamma ERT
+ module = new /obj/item/robot_module/combat(src)
+ icon_state = "ertgamma"
+ status_flags &= ~CANPUSH
if("Hunter")
module = new /obj/item/robot_module/alien/hunter(src)
@@ -441,6 +463,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
ionpulse = FALSE
magpulse = FALSE
add_language("Robot Talk", 1)
+ if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
+ weather_immunities -= "lava"
status_flags |= CANPUSH
@@ -840,7 +864,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
else
sleep(6)
- emagged = 1
+ SetEmagged(TRUE)
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
if(src.hud_used)
src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
@@ -915,7 +939,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return 0
/mob/living/silicon/robot/update_icons()
-
overlays.Cut()
if(stat != DEAD && !(paralysis || stunned || IsWeakened() || low_power_mode)) //Not dead, not stunned.
if(custom_panel in custom_eye_names)
@@ -924,36 +947,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
-
if(opened)
var/panelprefix = "ov"
if(custom_sprite) //Custom borgs also have custom panels, heh
panelprefix = "[ckey]"
-
if(custom_panel in custom_panel_names) //For default borgs with different panels
panelprefix = custom_panel
-
if(wiresexposed)
overlays += "[panelprefix]-openpanel +w"
else if(cell)
overlays += "[panelprefix]-openpanel +c"
else
overlays += "[panelprefix]-openpanel -c"
-
- var/combat = list("Combat")
- if(modtype in combat)
- if(base_icon == "")
- base_icon = icon_state
- if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
- icon_state = "[base_icon]-roll"
- else
- icon_state = base_icon
- if(module)
- for(var/obj/item/borg/combat/shield/S in module.modules)
- if(activated(S))
- overlays += "[base_icon]-shield"
+ borg_icons()
update_fire()
+/mob/living/silicon/robot/proc/borg_icons() // Exists so that robot/destroyer can override it
+ return
+
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]")
@@ -1133,13 +1144,13 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(!updating)
updating = 1
spawn(BORG_CAMERA_BUFFER)
- if(oldLoc != src.loc)
+ if(camera && oldLoc != src.loc)
GLOB.cameranet.updatePortableCamera(src.camera)
updating = 0
if(module)
if(module.type == /obj/item/robot_module/janitor)
var/turf/tile = loc
- if(isturf(tile))
+ if(stat != DEAD && isturf(tile))
var/floor_only = TRUE
for(var/A in tile)
if(istype(A, /obj/effect))
@@ -1157,16 +1168,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
- cleaned_human.update_inv_head(0,0)
+ cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
- cleaned_human.update_inv_wear_suit(0,0)
+ cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
- cleaned_human.update_inv_w_uniform(0,0)
+ cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
- cleaned_human.update_inv_shoes(0,0)
+ cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
to_chat(cleaned_human, "[src] cleans your face!")
if(floor_only)
@@ -1308,56 +1319,52 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
..()
update_module_icon()
+/mob/living/silicon/robot/emp_act(severity)
+ if(emp_protection)
+ return
+ ..()
+ switch(severity)
+ if(1)
+ disable_component("comms", 160)
+ if(2)
+ disable_component("comms", 60)
+
/mob/living/silicon/robot/deathsquad
base_icon = "nano_bloodhound"
icon_state = "nano_bloodhound"
designation = "SpecOps"
lawupdate = 0
scrambledcodes = 1
+ has_camera = FALSE
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
magpulse = 1
pdahide = 1
eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
ear_protection = 1 // Immunity to the audio part of flashbangs
+ damage_protection = 10 // Reduce all incoming damage by this number
+ xeno_disarm_chance = 20
allow_rename = FALSE
modtype = "Commando"
faction = list("nanotrasen")
is_emaggable = FALSE
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
-/mob/living/silicon/robot/deathsquad/New(loc)
- ..()
- cell = new /obj/item/stock_parts/cell/hyper(src)
-
-/mob/living/silicon/robot/deathsquad/init()
+/mob/living/silicon/robot/deathsquad/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/deathsquad
module = new /obj/item/robot_module/deathsquad(src)
-
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
radio = new /obj/item/radio/borg/deathsquad(src)
radio.recalculateChannels()
-
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
-/mob/living/silicon/robot/combat
- base_icon = "droidcombat"
- icon_state = "droidcombat"
- modtype = "Combat"
- designation = "Combat"
+/mob/living/silicon/robot/deathsquad/bullet_act(var/obj/item/projectile/P)
+ if(istype(P) && P.is_reflectable && P.starting)
+ visible_message("The [P.name] gets reflected by [src]!", "The [P.name] gets reflected by [src]!")
+ P.reflect_back(src)
+ return -1
+ return ..(P)
-/mob/living/silicon/robot/combat/init()
- ..()
- module = new /obj/item/robot_module/combat(src)
- module.channels = list("Security" = 1)
- //languages
- module.add_languages(src)
- //subsystems
- module.add_subsystems_and_actions(src)
-
- status_flags &= ~CANPUSH
-
- radio.config(module.channels)
- notify_ai(2)
/mob/living/silicon/robot/ert
designation = "ERT"
@@ -1365,24 +1372,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scrambledcodes = 1
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
-
force_modules = list("Engineering", "Medical", "Security")
static_radio_channels = 1
allow_rename = FALSE
weapons_unlock = TRUE
+ default_cell_type = /obj/item/stock_parts/cell/super
+ var/eprefix = "Amber"
-/mob/living/silicon/robot/ert/init()
+/mob/living/silicon/robot/ert/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/ert_override
radio = new /obj/item/radio/borg/ert(src)
radio.recalculateChannels()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
-/mob/living/silicon/robot/ert/New(loc, cyborg_unlock)
+/mob/living/silicon/robot/ert/New(loc)
..(loc)
- cell = new /obj/item/stock_parts/cell/hyper(src)
var/rnum = rand(1,1000)
- var/borgname = "ERT [rnum]"
+ var/borgname = "[eprefix] ERT [rnum]"
name = borgname
custom_name = borgname
real_name = name
@@ -1391,22 +1398,64 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mind.original = src
mind.assigned_role = SPECIAL_ROLE_ERT
mind.special_role = SPECIAL_ROLE_ERT
- if(cyborg_unlock)
- crisis = 1
if(!(mind in SSticker.minds))
SSticker.minds += mind
SSticker.mode.ert += mind
-/mob/living/silicon/robot/ert/gamma
- crisis = 1
-/mob/living/silicon/robot/emp_act(severity)
+/mob/living/silicon/robot/ert/red
+ eprefix = "Red"
+ default_cell_type = /obj/item/stock_parts/cell/hyper
+
+/mob/living/silicon/robot/ert/gamma
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
+ force_modules = list("Combat", "Engineering", "Medical")
+ damage_protection = 5 // Reduce all incoming damage by this number
+ eprefix = "Gamma"
+ magpulse = 1
+ xeno_disarm_chance = 40
+
+
+/mob/living/silicon/robot/destroyer
+ // admin-only borg, the seraph / special ops officer of borgs
+ base_icon = "droidcombat"
+ icon_state = "droidcombat"
+ modtype = "Destroyer"
+ designation = "Destroyer"
+ lawupdate = 0
+ scrambledcodes = 1
+ has_camera = FALSE
+ req_one_access = list(ACCESS_CENT_SPECOPS)
+ ionpulse = 1
+ magpulse = 1
+ pdahide = 1
+ eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
+ ear_protection = 1 // Immunity to the audio part of flashbangs
+ emp_protection = TRUE // Immunity to EMP, due to heavy shielding
+ damage_protection = 20 // Reduce all incoming damage by this number. Very high in the case of /destroyer borgs, since it is an admin-only borg.
+ xeno_disarm_chance = 10
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
+
+/mob/living/silicon/robot/destroyer/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
- switch(severity)
- if(1)
- disable_component("comms", 160)
- if(2)
- disable_component("comms", 60)
+ module = new /obj/item/robot_module/destroyer(src)
+ module.add_languages(src)
+ module.add_subsystems_and_actions(src)
+ status_flags &= ~CANPUSH
+ if(radio)
+ qdel(radio)
+ radio = new /obj/item/radio/borg/ert/specops(src)
+ radio.recalculateChannels()
+
+/mob/living/silicon/robot/destroyer/borg_icons()
+ if(base_icon == "")
+ base_icon = icon_state
+ if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
+ icon_state = "[base_icon]-roll"
+ else
+ icon_state = base_icon
+ overlays += "[base_icon]-shield"
+
/mob/living/silicon/robot/extinguish_light()
update_headlamp(1, 150)
@@ -1472,3 +1521,35 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
+
+/// Used in `robot_bindings.dm` when the user presses "A" if on AZERTY mode, or "Q" on QWERTY mode.
+/mob/living/silicon/robot/proc/on_drop_hotkey_press()
+ var/obj/item/gripper/G = get_active_hand()
+ if(istype(G) && G.gripped_item)
+ G.drop_gripped_item() // if the active module is a gripper, try to drop its held item.
+ else
+ uneq_active() // else unequip the module and put it back into the robot's inventory.
+ return
+
+/mob/living/silicon/robot/proc/check_module_damage(makes_sound = TRUE)
+ if(modules_break)
+ if(health < 50) //Gradual break down of modules as more damage is sustained
+ if(uneq_module(module_state_3))
+ if(makes_sound)
+ audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 3 OFFLINE.\"")
+ playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, TRUE)
+ to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.")
+
+ if(health < 0)
+ if(uneq_module(module_state_2))
+ if(makes_sound)
+ audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 2 OFFLINE.\"")
+ playsound(loc, 'sound/machines/warning-buzzer.ogg', 60, TRUE)
+ to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.")
+
+ if(health < -50)
+ if(uneq_module(module_state_1))
+ if(makes_sound)
+ audible_message("[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"")
+ playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE)
+ to_chat(src, "CRITICAL ERROR: All modules OFFLINE.")
diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm
index c73d566b729..b7b81ed40b7 100644
--- a/code/modules/mob/living/silicon/robot/robot_damage.dm
+++ b/code/modules/mob/living/silicon/robot/robot_damage.dm
@@ -1,12 +1,6 @@
/mob/living/silicon/robot/updatehealth(reason = "none given")
- if(status_flags & GODMODE)
- health = maxHealth
- stat = CONSCIOUS
- return
- health = maxHealth - (getOxyLoss() + getFireLoss() + getBruteLoss())
- update_stat("updatehealth([reason])")
- handle_hud_icons_health()
- diag_hud_set_health()
+ ..(reason)
+ check_module_damage()
/mob/living/silicon/robot/getBruteLoss(repairable_only = FALSE)
var/amount = 0
@@ -72,7 +66,7 @@
/mob/living/silicon/robot/heal_organ_damage(brute, burn, updating_health = TRUE)
var/list/datum/robot_component/parts = get_damaged_components(brute, burn)
- if(!LAZYLEN(parts))
+ if(!LAZYLEN(parts))
return
var/datum/robot_component/picked = pick(parts)
picked.heal_damage(brute, burn, updating_health)
@@ -82,29 +76,6 @@
if(!LAZYLEN(components))
return
- //Combat shielding absorbs a percentage of damage directly into the cell.
- var/obj/item/borg/combat/shield/shield
- if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
- shield = module_state_1
- else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
- shield = module_state_2
- else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
- shield = module_state_3
- if(shield)
- //Shields absorb a certain percentage of damage based on their power setting.
- var/absorb_brute = brute * shield.shield_level
- var/absorb_burn = burn * shield.shield_level
- var/cost = (absorb_brute+absorb_burn) * 100
-
- cell.charge -= cost
- if(cell.charge <= 0)
- cell.charge = 0
- to_chat(src, "Your shield has overloaded!")
- else
- brute -= absorb_brute
- burn -= absorb_burn
- to_chat(src, "Your shield absorbs some of the impact!")
-
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp, updating_health)
@@ -133,32 +104,15 @@
updatehealth("heal overall damage")
/mob/living/silicon/robot/take_overall_damage(brute = 0, burn = 0, updating_health = TRUE, used_weapon = null, sharp = 0)
- if(status_flags & GODMODE) return //godmode
+ if(status_flags & GODMODE)
+ return
+
+ if(damage_protection)
+ brute = clamp(brute - damage_protection, 0, brute)
+ burn = clamp(burn - damage_protection, 0, burn)
+
var/list/datum/robot_component/parts = get_damageable_components()
- //Combat shielding absorbs a percentage of damage directly into the cell.
- var/obj/item/borg/combat/shield/shield
- if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
- shield = module_state_1
- else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
- shield = module_state_2
- else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
- shield = module_state_3
- if(shield)
- //Shields absorb a certain percentage of damage based on their power setting.
- var/absorb_brute = brute * shield.shield_level
- var/absorb_burn = burn * shield.shield_level
- var/cost = (absorb_brute+absorb_burn) * 100
-
- cell.charge -= cost
- if(cell.charge <= 0)
- cell.charge = 0
- to_chat(src, "Your shield has overloaded!")
- else
- brute -= absorb_brute
- burn -= absorb_burn
- to_chat(src, "Your shield absorbs some of the impact!")
-
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp)
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index 9b4f1089f46..8445a399582 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -2,7 +2,7 @@
if(M.a_intent == INTENT_DISARM)
if(!lying)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
- if(prob(85))
+ if(prob(xeno_disarm_chance))
Stun(7)
step(src, get_dir(M,src))
spawn(5)
diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm
index 92115986b2e..b1abb49d2ef 100644
--- a/code/modules/mob/living/silicon/robot/robot_items.dm
+++ b/code/modules/mob/living/silicon/robot/robot_items.dm
@@ -73,24 +73,7 @@
/obj/item/borg
var/powerneeded // Percentage of power remaining required to run item
-/obj/item/borg/combat/shield
- name = "personal shielding"
- desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
- icon = 'icons/obj/decals.dmi'
- icon_state = "shock"
- powerneeded = 25
- var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
-
-/obj/item/borg/combat/shield/verb/set_shield_level()
- set name = "Set shield level"
- set category = "Object"
- set src in range(0)
-
- var/N = input("How much damage should the shield absorb?") in list("5","10","25","50","75","100")
- if(N)
- shield_level = text2num(N)/100
-
-/obj/item/borg/combat/mobility
+/obj/item/borg/destroyer/mobility
name = "mobility module"
desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds."
icon = 'icons/obj/decals.dmi'
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 47dcb93cef5..8e8c67693c5 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -118,20 +118,48 @@
return
/obj/item/robot_module/standard
- name = "standard robot module"
+ // if station is fine, assist with constructing station goal room, cleaning, and repairing cables chewed by rats
+ // if medical crisis, assist by providing basic healthcare, retrieving corpses, and monitoring crew lifesigns
+ // if eng crisis, assist by helping repair hull breaches
+ // if sec crisis, assist by opening doors for sec and providing backup zipties on patrols
+ name = "generalist robot module"
module_type = "Standard"
+ subsystems = list(/mob/living/silicon/proc/subsystem_power_monitor, /mob/living/silicon/proc/subsystem_crew_monitor)
+ stacktypes = list(
+ /obj/item/stack/sheet/metal/cyborg = 50,
+ /obj/item/stack/cable_coil/cyborg = 50,
+ /obj/item/stack/rods/cyborg = 60,
+ /obj/item/stack/tile/plasteel = 20
+ )
/obj/item/robot_module/standard/New()
..()
- modules += new /obj/item/melee/baton/loaded(src)
- modules += new /obj/item/extinguisher(src)
- modules += new /obj/item/wrench/cyborg(src)
+ // sec
+ modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
+ // janitorial
+ modules += new /obj/item/soap/nanotrasen(src)
+ modules += new /obj/item/lightreplacer/cyborg(src)
+ // eng
modules += new /obj/item/crowbar/cyborg(src)
+ modules += new /obj/item/wrench/cyborg(src)
+ modules += new /obj/item/extinguisher(src) // for firefighting, and propulsion in space
+ modules += new /obj/item/weldingtool/largetank/cyborg(src)
+ // mining
+ modules += new /obj/item/pickaxe(src)
+ modules += new /obj/item/t_scanner/adv_mining_scanner(src)
+ modules += new /obj/item/storage/bag/ore/cyborg(src)
+ // med
modules += new /obj/item/healthanalyzer(src)
+ modules += new /obj/item/reagent_containers/borghypo/basic(src)
+ modules += new /obj/item/roller_holder(src) // for taking the injured to medbay without worsening their injuries or leaving a blood trail the whole way
emag = new /obj/item/melee/energy/sword/cyborg(src)
-
+ for(var/G in stacktypes)
+ var/obj/item/stack/sheet/M = new G(src)
+ M.amount = stacktypes[G]
+ modules += M
fix_modules()
+
/obj/item/robot_module/medical
name = "medical robot module"
module_type = "Medical"
@@ -230,7 +258,7 @@
/obj/item/robot_module/engineering/handle_death()
var/obj/item/gripper/G = locate(/obj/item/gripper) in modules
if(G)
- G.drop_item()
+ G.drop_gripped_item(silent = TRUE)
/obj/item/robot_module/security
name = "security robot module"
@@ -259,6 +287,7 @@
modules += new /obj/item/mop/advanced/cyborg(src)
modules += new /obj/item/lightreplacer/cyborg(src)
modules += new /obj/item/holosign_creator(src)
+ modules += new /obj/item/extinguisher/mini(src)
emag = new /obj/item/reagent_containers/spray(src)
emag.reagents.add_reagent("lube", 250)
@@ -483,25 +512,44 @@
fix_modules()
-/obj/item/robot_module/combat
- name = "combat robot module"
+/obj/item/robot_module/destroyer
+ name = "destroyer robot module"
module_type = "Malf"
module_actions = list(
/datum/action/innate/robot_sight/thermal,
)
+/obj/item/robot_module/destroyer/New()
+ ..()
+
+ modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // See comments on /robot_module/combat below
+ modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
+ modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
+ modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
+ modules += new /obj/item/borg/destroyer/mobility(src)
+ emag = null
+ fix_modules()
+
+
+/obj/item/robot_module/combat
+ name = "combat robot module"
+ module_type = "Malf"
+ module_actions = list()
+
/obj/item/robot_module/combat/New()
..()
+ modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // primary weapon, strong at close range (ie: against blob/terror/xeno), but consumes a lot of energy per shot.
+ // Borg gets 40 shots of this weapon. Gamma Sec ERT gets 10.
+ // So, borg has way more burst damage, but also takes way longer to recharge / get back in the fight once depleted. Has to find a borg recharger and sit in it for ages.
+ // Organic gamma sec ERT carries alternate weapons, including a box of flashbangs, and can load up on a huge number of guns from science. Borg cannot do either.
+ // Overall, gamma borg has higher skill floor but lower skill ceiling.
+ modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
- modules += new /obj/item/gun/energy/gun/cyborg(src)
- modules += new /obj/item/pickaxe/drill/jackhammer(src)
- modules += new /obj/item/borg/combat/shield(src)
- modules += new /obj/item/borg/combat/mobility(src)
- modules += new /obj/item/wrench/cyborg(src)
- emag = new /obj/item/gun/energy/lasercannon/cyborg(src)
-
+ modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
+ emag = null
fix_modules()
+
/obj/item/robot_module/alien/hunter
name = "alien hunter module"
module_type = "Standard"
@@ -578,7 +626,7 @@
/obj/item/robot_module/drone/handle_death()
var/obj/item/gripper/G = locate(/obj/item/gripper) in modules
if(G)
- G.drop_item()
+ G.drop_gripped_item(silent = TRUE)
//checks whether this item is a module of the robot it is located in.
/obj/item/proc/is_robot_module()
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index 4b645b02849..1d3e1cade6d 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -9,7 +9,7 @@
/mob/living/silicon/robot/movement_delay()
. = ..()
. += speed
- if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
+ if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
. -= 3
. += config.robot_delay
diff --git a/code/modules/mob/living/silicon/robot/syndicate.dm b/code/modules/mob/living/silicon/robot/syndicate.dm
index 2b5fd9bb702..f5b58696059 100644
--- a/code/modules/mob/living/silicon/robot/syndicate.dm
+++ b/code/modules/mob/living/silicon/robot/syndicate.dm
@@ -3,8 +3,10 @@
icon_state = "syndie_bloodhound"
lawupdate = 0
scrambledcodes = 1
+ has_camera = FALSE
pdahide = 1
faction = list("syndicate")
+ bubble_icon = "syndibot"
designation = "Syndicate Assault"
modtype = "Syndicate"
req_access = list(ACCESS_SYNDICATE)
@@ -19,7 +21,7 @@
..()
cell = new /obj/item/stock_parts/cell/hyper(src)
-/mob/living/silicon/robot/syndicate/init()
+/mob/living/silicon/robot/syndicate/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/syndicate_override
module = new /obj/item/robot_module/syndicate(src)
@@ -45,7 +47,7 @@
Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
Help the operatives secure the disk at all costs!"
-/mob/living/silicon/robot/syndicate/medical/init()
+/mob/living/silicon/robot/syndicate/medical/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_medical(src)
@@ -65,7 +67,7 @@
Be aware that physical contact or taking damage will break your disguise. \
Help the operatives secure the disk at all costs!"
-/mob/living/silicon/robot/syndicate/saboteur/init()
+/mob/living/silicon/robot/syndicate/saboteur/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_saboteur(src)
@@ -137,9 +139,9 @@
..()
/mob/living/silicon/robot/syndicate/saboteur/emp_act()
+ ..()
if(cham_proj)
cham_proj.disrupt(src)
- ..()
/mob/living/silicon/robot/syndicate/saboteur/bullet_act()
if(cham_proj)
diff --git a/code/modules/mob/living/silicon/robot/update_status.dm b/code/modules/mob/living/silicon/robot/update_status.dm
index 5f1519395c7..91f9952c075 100644
--- a/code/modules/mob/living/silicon/robot/update_status.dm
+++ b/code/modules/mob/living/silicon/robot/update_status.dm
@@ -17,10 +17,12 @@
if(!is_component_functioning("actuator") || !is_component_functioning("power cell") || paralysis || sleeping || resting || stunned || IsWeakened() || getOxyLoss() > maxHealth * 0.5)
if(stat == CONSCIOUS)
KnockOut()
+ update_headlamp()
create_debug_log("fell unconscious, trigger reason: [reason]")
else
if(stat == UNCONSCIOUS)
WakeUp()
+ update_headlamp()
create_debug_log("woke up, trigger reason: [reason]")
else
if(health > 0)
@@ -31,9 +33,10 @@
ghost << sound('sound/effects/genetics.ogg')
create_attack_log("revived, trigger reason: [reason]")
create_log(MISC_LOG, "revived, trigger reason: [reason]")
- // diag_hud_set_status()
- // diag_hud_set_health()
- // update_health_hud()
+
+ diag_hud_set_status()
+ diag_hud_set_health()
+ update_health_hud()
/mob/living/silicon/robot/SetStunned(amount, updating = 1, force = 0) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned"
. = STATUS_UPDATE_CANMOVE
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index a62f5f9d358..c923e0912b7 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -2,7 +2,9 @@
gender = NEUTER
robot_talk_understand = 1
voice_name = "synthesized voice"
+ bubble_icon = "machine"
has_unlimited_silicon_privilege = 1
+ weather_immunities = list("ash")
var/syndicate = 0
var/const/MAIN_CHANNEL = "Main Frequency"
var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws
@@ -76,23 +78,23 @@
return FALSE //So borgs they don't die trying to fix wiring
/mob/living/silicon/emp_act(severity)
+ ..()
switch(severity)
if(1)
- src.take_organ_damage(20)
+ take_organ_damage(20)
Stun(8)
if(2)
- src.take_organ_damage(10)
+ take_organ_damage(10)
Stun(3)
flash_eyes(affect_silicon = 1)
to_chat(src, "*BZZZT*")
to_chat(src, "Warning: Electromagnetic pulse detected.")
- ..()
/mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0)
return
-/mob/living/silicon/can_inject(mob/user, error_msg)
+/mob/living/silicon/can_inject(mob/user, error_msg, target_zone, penetrate_thick)
if(error_msg)
to_chat(user, "[p_their(TRUE)] outer shell is too tough.")
return FALSE
@@ -283,7 +285,7 @@
/mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised)
if(!next_alarm_notice)
- next_alarm_notice = world.time + SecondsToTicks(10)
+ next_alarm_notice = world.time + 10 SECONDS
var/list/alarms = queued_alarms[alarm_handler]
if(was_raised)
diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm
index 5f00beff1e4..d18d41a40cf 100644
--- a/code/modules/mob/living/silicon/subsystems.dm
+++ b/code/modules/mob/living/silicon/subsystems.dm
@@ -2,7 +2,7 @@
var/register_alarms = 1
var/datum/nano_module/alarm_monitor/all/alarm_monitor
var/datum/nano_module/atmos_control/atmos_control
- var/datum/nano_module/crew_monitor/crew_monitor
+ var/datum/tgui_module/crew_monitor/crew_monitor
var/datum/nano_module/law_manager/law_manager
var/datum/nano_module/power_monitor/silicon/power_monitor
@@ -71,8 +71,7 @@
/mob/living/silicon/proc/subsystem_crew_monitor()
set category = "Subsystems"
set name = "Crew Monitor"
-
- crew_monitor.ui_interact(usr, state = GLOB.self_state)
+ crew_monitor.tgui_interact(usr, state = GLOB.tgui_self_state)
/****************
* Law Manager *
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 2cfc5e746dc..b42f3275997 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -118,7 +118,7 @@
/mob/living/simple_animal/blob_act(obj/structure/blob/B)
adjustBruteLoss(20)
-/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
if(melee_damage_upper < 10)
visual_effect_icon = ATTACK_EFFECT_PUNCH
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index ede055dac43..e51dc527832 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -18,7 +18,7 @@
speak_emote = list("states")
friendly = "boops"
-
+ bubble_icon = "machine"
faction = list("neutral", "silicon")
var/obj/machinery/bot_core/bot_core = null
@@ -63,6 +63,7 @@
var/new_destination // pending new destination (waiting for beacon response)
var/destination // destination description tag
var/next_destination // the next destination in the patrol route
+ var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list
var/robot_arm = /obj/item/robot_parts/r_arm
var/blockcount = 0 //number of times retried a blocked path
@@ -94,6 +95,7 @@
/obj/item/radio/headset/bot
subspace_transmission = 1
+ requires_tcomms = FALSE
canhear_range = 0
/obj/item/radio/headset/bot/recalculateChannels()
@@ -253,6 +255,15 @@
/mob/living/simple_animal/bot/handle_automated_action()
diag_hud_set_botmode()
+ if(ignorelistcleanuptimer % 300 == 0) // Every 300 actions, clean up the ignore list from old junk
+ for(var/uid in ignore_list)
+ var/atom/referredatom = locateUID(uid)
+ if(!referredatom || QDELETED(referredatom))
+ ignore_list -= uid
+ ignorelistcleanuptimer = 1
+ else
+ ignorelistcleanuptimer++
+
if(!on)
return
@@ -438,14 +449,15 @@ Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1)
The proc would return a human next to the bot to be set to the patient var.
Pass the desired type path itself, declaring a temporary var beforehand is not required.
*/
-/mob/living/simple_animal/bot/proc/scan(scan_type, old_target, scan_range = DEFAULT_SCAN_RANGE)
+/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE)
var/final_result
for(var/scan in shuffle(view(scan_range, src))) //Search for something in range!
- if(!istype(scan, scan_type)) //Check that the thing we found is the type we want!
+ var/atom/A = scan
+ if(!istype(A, scan_type)) //Check that the thing we found is the type we want!
continue //If not, keep searching!
- if( (scan in ignore_list) || (scan == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
+ if((A.UID() in ignore_list) || (A == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
continue
- var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected.
+ var/scan_result = process_scan(A) //Some bots may require additional processing when a result is selected.
if(scan_result)
final_result = scan_result
else
@@ -453,17 +465,16 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
return final_result
//When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
-/mob/living/simple_animal/bot/proc/process_scan(scan_target)
+/mob/living/simple_animal/bot/proc/process_scan(atom/scan_target)
return scan_target
-/mob/living/simple_animal/bot/proc/add_to_ignore(subject)
+/mob/living/simple_animal/bot/proc/add_to_ignore(atom/A)
if(ignore_list.len < 50) //This will help keep track of them, so the bot is always trying to reach a blocked spot.
- ignore_list |= subject
- else if(ignore_list.len >= subject) //If the list is full, insert newest, delete oldest.
- ignore_list -= ignore_list[1]
- ignore_list |= subject
-
+ ignore_list |= A.UID()
+ else //If the list is full, insert newest, delete oldest.
+ ignore_list.Cut(1, 2)
+ ignore_list |= A.UID()
/*
Movement proc for stepping a bot through a path generated through A-star.
Pass a positive integer as an argument to override a bot's default speed.
@@ -495,7 +506,7 @@ Pass a positive integer as an argument to override a bot's default speed.
if(!path)
return 0
if(path.len > 1)
- step_towards(src, path[1])
+ Move(path[1], get_dir(src, path[1]), BOT_STEP_DELAY)
if(get_turf(src) == path[1]) //Successful move
increment_path()
tries = 0
@@ -745,7 +756,7 @@ Pass a positive integer as an argument to override a bot's default speed.
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/proc/post_signal_multiple(var/freq, var/list/keyval)
- if(z != 1) //Bot control will only work on station.
+ if(!is_station_level(z)) //Bot control will only work on station.
return
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
@@ -1030,20 +1041,6 @@ Pass a positive integer as an argument to override a bot's default speed.
Radio.talk_into(src, message, message_mode, verb, speaking)
used_radios += Radio
-/mob/living/simple_animal/bot/handle_hud_icons_health()
- ..()
- switch(bodytemperature) //310.055 optimal body temp
- if(335 to INFINITY)
- throw_alert("temp", /obj/screen/alert/hot/robot, 2)
- if(320 to 335)
- throw_alert("temp", /obj/screen/alert/hot/robot, 1)
- if(300 to 320)
- clear_alert("temp")
- if(260 to 300)
- throw_alert("temp", /obj/screen/alert/cold/robot, 1)
- else
- throw_alert("temp", /obj/screen/alert/cold/robot, 2)
-
/mob/living/simple_animal/bot/is_mechanical()
return 1
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index f9747238138..4cb4a532d6b 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -50,7 +50,7 @@
/mob/living/simple_animal/bot/cleanbot/bot_reset()
..()
- ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
+ ignore_list.Cut() //Allows the bot to clean targets it previously ignored due to being unreachable.
target = null
oldloc = null
@@ -106,7 +106,7 @@
audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
- target = scan(/obj/effect/decal/cleanable/)
+ target = scan(/obj/effect/decal/cleanable)
if(!target && auto_patrol) //Search for cleanables it can see.
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 024e2b5f304..e18672ffa20 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -474,8 +474,7 @@
return
build_step++
to_chat(user, "You complete the Securitron! Beep boop.")
- var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
- S.forceMove(get_turf(src))
+ var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot(get_turf(src))
S.name = created_name
S.robot_arm = robot_arm
qdel(I)
@@ -512,7 +511,7 @@
//General Griefsky
else if((istype(I, /obj/item/wrench)) && (build_step == 3))
- var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly
+ var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly(get_turf(src))
user.put_in_hands(A)
to_chat(user, "You adjust the arm slots for extra weapons!.")
user.unEquip(src, 1)
@@ -540,8 +539,7 @@
if(!user.unEquip(I))
return
to_chat(user, "You complete General Griefsky!.")
- var/mob/living/simple_animal/bot/secbot/griefsky/S = new /mob/living/simple_animal/bot/secbot/griefsky
- S.forceMove(get_turf(src))
+ new /mob/living/simple_animal/bot/secbot/griefsky(get_turf(src))
qdel(I)
qdel(src)
@@ -556,8 +554,7 @@
if(!user.unEquip(I))
return
to_chat(user, "You complete Genewul Giftskee!.")
- var/mob/living/simple_animal/bot/secbot/griefsky/toy/S = new /mob/living/simple_animal/bot/secbot/griefsky/toy
- S.forceMove(get_turf(src))
+ new /mob/living/simple_animal/bot/secbot/griefsky/toy(get_turf(src))
qdel(I)
qdel(src)
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index 5b0ea28a72a..df96cae3b6b 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -56,7 +56,7 @@
..()
target = null
oldloc = null
- ignore_list = list()
+ ignore_list.Cut()
nagged = 0
anchored = FALSE
update_icon()
@@ -270,7 +270,7 @@
return 1
//Floorbots, having several functions, need sort out special conditions here.
-/mob/living/simple_animal/bot/floorbot/process_scan(scan_target)
+/mob/living/simple_animal/bot/floorbot/process_scan(atom/scan_target)
var/result
var/turf/simulated/floor/F
switch(process_type)
diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm
index d9097a82d2e..62c133fffd7 100644
--- a/code/modules/mob/living/simple_animal/bot/honkbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm
@@ -33,7 +33,7 @@
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME)
-/mob/living/simple_animal/bot/honkbot/Initialize()
+/mob/living/simple_animal/bot/honkbot/Initialize(mapload)
. = ..()
update_icon()
auto_patrol = TRUE
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index c89b160bf0e..f1278918898 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -323,13 +323,13 @@
/mob/living/simple_animal/bot/mulebot/proc/buzz(type)
switch(type)
if(SIGH)
- audible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
+ audible_message("[src] makes a sighing buzz.")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
if(ANNOYED)
- audible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.")
+ audible_message("[src] makes an annoyed buzzing sound.")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
if(DELIGHT)
- audible_message("[src] makes a delighted ping!", "You hear a ping.")
+ audible_message("[src] makes a delighted ping!")
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
@@ -391,8 +391,6 @@
passenger = M
load = M
can_buckle = FALSE
- // Not sure why this is done
- reset_perspective(src)
return TRUE
return FALSE
@@ -417,9 +415,6 @@
overlays.Cut()
- if(ismob(load))
- var/mob/M = load
- M.reset_perspective(null)
unbuckle_all_mobs()
if(load)
@@ -446,9 +441,6 @@
AM.layer = initial(AM.layer)
AM.pixel_y = initial(AM.pixel_y)
AM.plane = initial(AM.plane)
- if(ismob(AM))
- var/mob/M = AM
- M.reset_perspective(null)
/mob/living/simple_animal/bot/mulebot/call_bot()
..()
@@ -609,7 +601,7 @@
/mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target)
radio_channel = "Supply" //Supply channel
- audible_message("[src] makes a chiming sound!", "You hear a chime.")
+ audible_message("[src] makes a chiming sound!")
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
reached_target = 1
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index ee03c204d48..f150005116e 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -333,73 +333,116 @@
///ui stuff
-/mob/living/simple_animal/hostile/construct/armoured/handle_hud_icons_health()
- ..()
+/mob/living/simple_animal/hostile/construct/armoured/update_health_hud()
+ if(!client)
+ return
if(healths)
switch(health)
- if(250 to INFINITY) healths.icon_state = "juggernaut_health0"
- if(208 to 249) healths.icon_state = "juggernaut_health1"
- if(167 to 207) healths.icon_state = "juggernaut_health2"
- if(125 to 166) healths.icon_state = "juggernaut_health3"
- if(84 to 124) healths.icon_state = "juggernaut_health4"
- if(42 to 83) healths.icon_state = "juggernaut_health5"
- if(1 to 41) healths.icon_state = "juggernaut_health6"
- else healths.icon_state = "juggernaut_health7"
+ if(250 to INFINITY)
+ healths.icon_state = "juggernaut_health0"
+ if(208 to 249)
+ healths.icon_state = "juggernaut_health1"
+ if(167 to 207)
+ healths.icon_state = "juggernaut_health2"
+ if(125 to 166)
+ healths.icon_state = "juggernaut_health3"
+ if(84 to 124)
+ healths.icon_state = "juggernaut_health4"
+ if(42 to 83)
+ healths.icon_state = "juggernaut_health5"
+ if(1 to 41)
+ healths.icon_state = "juggernaut_health6"
+ else
+ healths.icon_state = "juggernaut_health7"
-/mob/living/simple_animal/hostile/construct/behemoth/handle_hud_icons_health()
- ..()
+/mob/living/simple_animal/hostile/construct/behemoth/update_health_hud()
+ if(!client)
+ return
if(healths)
switch(health)
- if(750 to INFINITY) healths.icon_state = "juggernaut_health0"
- if(625 to 749) healths.icon_state = "juggernaut_health1"
- if(500 to 624) healths.icon_state = "juggernaut_health2"
- if(375 to 499) healths.icon_state = "juggernaut_health3"
- if(250 to 374) healths.icon_state = "juggernaut_health4"
- if(125 to 249) healths.icon_state = "juggernaut_health5"
- if(1 to 124) healths.icon_state = "juggernaut_health6"
- else healths.icon_state = "juggernaut_health7"
+ if(750 to INFINITY)
+ healths.icon_state = "juggernaut_health0"
+ if(625 to 749)
+ healths.icon_state = "juggernaut_health1"
+ if(500 to 624)
+ healths.icon_state = "juggernaut_health2"
+ if(375 to 499)
+ healths.icon_state = "juggernaut_health3"
+ if(250 to 374)
+ healths.icon_state = "juggernaut_health4"
+ if(125 to 249)
+ healths.icon_state = "juggernaut_health5"
+ if(1 to 124)
+ healths.icon_state = "juggernaut_health6"
+ else
+ healths.icon_state = "juggernaut_health7"
-/mob/living/simple_animal/hostile/construct/builder/handle_hud_icons_health()
- ..()
+/mob/living/simple_animal/hostile/construct/builder/update_health_hud()
+ if(!client)
+ return
if(healths)
switch(health)
- if(50 to INFINITY) healths.icon_state = "artificer_health0"
- if(42 to 49) healths.icon_state = "artificer_health1"
- if(34 to 41) healths.icon_state = "artificer_health2"
- if(26 to 33) healths.icon_state = "artificer_health3"
- if(18 to 25) healths.icon_state = "artificer_health4"
- if(10 to 17) healths.icon_state = "artificer_health5"
- if(1 to 9) healths.icon_state = "artificer_health6"
- else healths.icon_state = "artificer_health7"
+ if(50 to INFINITY)
+ healths.icon_state = "artificer_health0"
+ if(42 to 49)
+ healths.icon_state = "artificer_health1"
+ if(34 to 41)
+ healths.icon_state = "artificer_health2"
+ if(26 to 33)
+ healths.icon_state = "artificer_health3"
+ if(18 to 25)
+ healths.icon_state = "artificer_health4"
+ if(10 to 17)
+ healths.icon_state = "artificer_health5"
+ if(1 to 9)
+ healths.icon_state = "artificer_health6"
+ else
+ healths.icon_state = "artificer_health7"
-/mob/living/simple_animal/hostile/construct/wraith/handle_hud_icons_health()
-
- ..()
+/mob/living/simple_animal/hostile/construct/wraith/update_health_hud()
+ if(!client)
+ return
if(healths)
switch(health)
- if(75 to INFINITY) healths.icon_state = "wraith_health0"
- if(62 to 74) healths.icon_state = "wraith_health1"
- if(50 to 61) healths.icon_state = "wraith_health2"
- if(37 to 49) healths.icon_state = "wraith_health3"
- if(25 to 36) healths.icon_state = "wraith_health4"
- if(12 to 24) healths.icon_state = "wraith_health5"
- if(1 to 11) healths.icon_state = "wraith_health6"
- else healths.icon_state = "wraith_health7"
+ if(75 to INFINITY)
+ healths.icon_state = "wraith_health0"
+ if(62 to 74)
+ healths.icon_state = "wraith_health1"
+ if(50 to 61)
+ healths.icon_state = "wraith_health2"
+ if(37 to 49)
+ healths.icon_state = "wraith_health3"
+ if(25 to 36)
+ healths.icon_state = "wraith_health4"
+ if(12 to 24)
+ healths.icon_state = "wraith_health5"
+ if(1 to 11)
+ healths.icon_state = "wraith_health6"
+ else
+ healths.icon_state = "wraith_health7"
-/mob/living/simple_animal/hostile/construct/harvester/handle_hud_icons_health()
-
- ..()
+/mob/living/simple_animal/hostile/construct/harvester/update_health_hud()
+ if(!client)
+ return
if(healths)
switch(health)
- if(150 to INFINITY) healths.icon_state = "harvester_health0"
- if(125 to 149) healths.icon_state = "harvester_health1"
- if(100 to 124) healths.icon_state = "harvester_health2"
- if(75 to 99) healths.icon_state = "harvester_health3"
- if(50 to 74) healths.icon_state = "harvester_health4"
- if(25 to 49) healths.icon_state = "harvester_health5"
- if(1 to 24) healths.icon_state = "harvester_health6"
- else healths.icon_state = "harvester_health7"
+ if(150 to INFINITY)
+ healths.icon_state = "harvester_health0"
+ if(125 to 149)
+ healths.icon_state = "harvester_health1"
+ if(100 to 124)
+ healths.icon_state = "harvester_health2"
+ if(75 to 99)
+ healths.icon_state = "harvester_health3"
+ if(50 to 74)
+ healths.icon_state = "harvester_health4"
+ if(25 to 49)
+ healths.icon_state = "harvester_health5"
+ if(1 to 24)
+ healths.icon_state = "harvester_health6"
+ else
+ healths.icon_state = "harvester_health7"
diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm
index 10460d11e65..8d0ad5d0e2b 100644
--- a/code/modules/mob/living/simple_animal/corpse.dm
+++ b/code/modules/mob/living/simple_animal/corpse.dm
@@ -103,9 +103,9 @@
name = "Space Wizard Corpse"
outfit = /datum/outfit/wizardcorpse
-/obj/effect/mob_spawn/human/corpse/clownoff/Initialize()
+/obj/effect/mob_spawn/human/corpse/clownoff/Initialize(mapload)
mob_name = "[pick(GLOB.wizard_first)], [pick(GLOB.wizard_second)]"
- ..()
+ . = ..()
/datum/outfit/wizardcorpse
name = "Space Wizard Corpse"
diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm
index 6ba69de6a61..fdcbf95216b 100644
--- a/code/modules/mob/living/simple_animal/damage_procs.dm
+++ b/code/modules/mob/living/simple_animal/damage_procs.dm
@@ -3,7 +3,7 @@
if(status_flags & GODMODE)
return FALSE
var/oldbruteloss = bruteloss
- bruteloss = Clamp(bruteloss + amount, 0, maxHealth)
+ bruteloss = clamp(bruteloss + amount, 0, maxHealth)
if(oldbruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm
index e8c108a11de..7d6f90b7d0d 100644
--- a/code/modules/mob/living/simple_animal/friendly/diona.dm
+++ b/code/modules/mob/living/simple_animal/friendly/diona.dm
@@ -202,6 +202,20 @@
qdel(src)
return TRUE
+// Consumes plant matter other than weeds to evolve
+/mob/living/simple_animal/diona/proc/consume(obj/item/reagent_containers/food/snacks/grown/G)
+ if(nutrition >= nutrition_need) // Prevents griefing by overeating plant items without evolving.
+ to_chat(src, "You're too full to consume this! Perhaps it's time to grow bigger...")
+ else
+ if(do_after_once(src, 20, target = G))
+ visible_message("[src] ravenously consumes [G].", "You ravenously devour [G].")
+ playsound(loc, 'sound/items/eatfood.ogg', 30, 0, frequency = 1.5)
+ if(G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter") < 1)
+ adjust_nutrition(2)
+ else
+ adjust_nutrition((G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter")) * 2)
+ qdel(G)
+
/mob/living/simple_animal/diona/proc/steal_blood()
if(stat != CONSCIOUS)
return FALSE
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index 4b29e703116..07a21af8a0b 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -153,16 +153,16 @@
if(def_zone)
if(def_zone == "head")
if(inventory_head)
- armorval = inventory_head.armor[type]
+ armorval = inventory_head.armor.getRating(type)
else
if(inventory_back)
- armorval = inventory_back.armor[type]
+ armorval = inventory_back.armor.getRating(type)
return armorval
else
if(inventory_head)
- armorval += inventory_head.armor[type]
+ armorval += inventory_head.armor.getRating(type)
if(inventory_back)
- armorval += inventory_back.armor[type]
+ armorval += inventory_back.armor.getRating(type)
return armorval * 0.5
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index 96688963b73..566791786f6 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -23,3 +23,14 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 1)
can_collar = 1
gold_core_spawnable = FRIENDLY_SPAWN
+
+/mob/living/simple_animal/lizard/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!istype(user, /mob/living/silicon/robot/drone))
+ user.visible_message("[user] sucks [src] into its decompiler. There's a horrible crunching noise.", \
+ "It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.")
+ new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
+ C.stored_comms["wood"] += 2
+ C.stored_comms["glass"] += 2
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 1446ef7d4bb..152e2494132 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -49,11 +49,11 @@
if(C.avail())
visible_message("[src] chews through [C]. It's toast!")
playsound(src, 'sound/effects/sparks2.ogg', 100, 1)
- C.deconstruct()
toast() // mmmm toasty.
else
- C.deconstruct()
visible_message("[src] chews through [C].")
+ investigate_log("was chewed through by a mouse in [get_area(F)]([F.x], [F.y], [F.z] - [ADMIN_JMP(F)])","wires")
+ C.deconstruct()
/mob/living/simple_animal/mouse/handle_automated_speech()
..()
@@ -234,3 +234,14 @@
gold_core_spawnable = NO_SPAWN
can_collar = 0
butcher_results = list(/obj/item/stack/sheet/metal = 1)
+
+/mob/living/simple_animal/mouse/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!(istype(user, /mob/living/silicon/robot/drone)))
+ user.visible_message("[user] sucks [src] into its decompiler. There's a horrible crunching noise.", \
+ "It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.")
+ new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
+ C.stored_comms["wood"] += 2
+ C.stored_comms["glass"] += 2
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm
index dc00e252661..08321b1bb5a 100644
--- a/code/modules/mob/living/simple_animal/friendly/penguin.dm
+++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm
@@ -18,7 +18,7 @@
/mob/living/simple_animal/pet/penguin/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/waddling)
+ AddElement(/datum/element/waddling)
/mob/living/simple_animal/pet/penguin/emperor
name = "Emperor penguin"
diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
index 7a1227960f4..877d542fa2b 100644
--- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
@@ -123,8 +123,6 @@
if(health >= maxHealth)
to_chat(user, "[src] does not need repairing!")
return
- to_chat(user, "Unable to repair with the maintenance panel closed!")
- return
. = TRUE
if(!I.use_tool(src, user, volume = I.tool_volume))
return
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 5a369a043d7..7c7b4dd6a2f 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -11,7 +11,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 3, /obj/item/stack/sheet/animalhide/xeno = 1)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 3, /obj/item/stack/sheet/animalhide/xeno = 1)
maxHealth = 125
health = 125
harm_intent_damage = 5
@@ -20,6 +20,7 @@
melee_damage_upper = 25
attacktext = "slashes"
speak_emote = list("hisses")
+ bubble_icon = "alien"
a_intent = INTENT_HARM
attack_sound = 'sound/weapons/bladeslice.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
@@ -83,7 +84,7 @@
retreat_distance = 5
minimum_distance = 5
move_to_delay = 4
- butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 4, /obj/item/stack/sheet/animalhide/xeno = 1)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 4, /obj/item/stack/sheet/animalhide/xeno = 1)
projectiletype = /obj/item/projectile/neurotox
projectilesound = 'sound/weapons/pierce.ogg'
status_flags = 0
@@ -127,10 +128,11 @@
icon_state = "queen_s"
icon_living = "queen_s"
icon_dead = "queen_dead"
+ bubble_icon = "alienroyal"
move_to_delay = 4
maxHealth = 400
health = 400
- butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 10, /obj/item/stack/sheet/animalhide/xeno = 2)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 10, /obj/item/stack/sheet/animalhide/xeno = 2)
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = NO_SPAWN
@@ -153,7 +155,7 @@
icon_dead = "maid_dead"
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
- if(ismovableatom(target))
+ if(ismovable(target))
if(istype(target, /obj/effect/decal/cleanable))
visible_message("\The [src] cleans up \the [target].")
qdel(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 2530fb4b389..d5b7205f09c 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -13,7 +13,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
- butcher_results = list(/obj/item/reagent_containers/food/snacks/bearmeat = 5, /obj/item/clothing/head/bearpelt = 1)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/bearmeat= 5, /obj/item/clothing/head/bearpelt = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index c1e7548d9a3..3419279ffe5 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -60,6 +60,7 @@
/mob/living/simple_animal/hostile/poison/bees/New()
..()
generate_bee_visuals()
+ AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/poison/bees/Destroy()
beegent = null
@@ -94,6 +95,10 @@
for(var/mob/A in searched_for)
. += A
+// All bee sprites are made up of overlays. They do not have any special sprite overlays for items placed on them, such as collars, so this proc is unneeded.
+/mob/living/simple_animal/hostile/poison/bees/regenerate_icons()
+ return
+
/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
overlays.Cut()
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index a0cb935ba25..7b0b52f0b4f 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -74,12 +74,11 @@
else
our_color = pick(carp_colors)
add_atom_colour(carp_colors[our_color], FIXED_COLOUR_PRIORITY)
- add_carp_overlay()
+ regenerate_icons()
/mob/living/simple_animal/hostile/carp/proc/add_carp_overlay()
if(!random_color)
return
- cut_overlays()
var/mutable_appearance/base_overlay = mutable_appearance(icon, "base_mouth")
base_overlay.appearance_flags = RESET_COLOR
add_overlay(base_overlay)
@@ -87,7 +86,6 @@
/mob/living/simple_animal/hostile/carp/proc/add_dead_carp_overlay()
if(!random_color)
return
- cut_overlays()
var/mutable_appearance/base_dead_overlay = mutable_appearance(icon, "base_dead_mouth")
base_dead_overlay.appearance_flags = RESET_COLOR
add_overlay(base_dead_overlay)
@@ -103,24 +101,22 @@
/mob/living/simple_animal/hostile/carp/death(gibbed)
. = ..()
- cut_overlays()
if(!random_color || gibbed)
return
- add_dead_carp_overlay()
+ regenerate_icons()
/mob/living/simple_animal/hostile/carp/revive()
..()
regenerate_icons()
/mob/living/simple_animal/hostile/carp/regenerate_icons()
- cut_overlays()
+ ..()
if(!random_color)
return
if(stat != DEAD)
add_carp_overlay()
else
add_dead_carp_overlay()
- ..()
/mob/living/simple_animal/hostile/carp/holocarp
icon_state = "holocarp"
diff --git a/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm b/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm
index c0dfa097f16..cf55824542a 100644
--- a/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm
+++ b/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm
@@ -285,7 +285,7 @@
if(prob(6))
for(var/turf/simulated/floor/O in range(src, 6))
- O.MakeSlippery(TURF_WET_WATER, 10)
+ O.MakeSlippery(TURF_WET_WATER, 10 SECONDS)
playsound(src, 'sound/effects/clownstep1.ogg', 30, 1)
if(prob(5))
@@ -323,7 +323,7 @@
if(!eating)
addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Grab, H), 70)
for(var/turf/simulated/floor/O in range(src, 6))
- O.MakeSlippery(TURF_WET_LUBE, 20)
+ O.MakeSlippery(TURF_WET_LUBE, 20 SECONDS)
playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1)
eating = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index b456db6efaf..614e814fc25 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -18,7 +18,7 @@
turns_per_move = 5
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
- butcher_results = list(/obj/item/reagent_containers/food/snacks/spidermeat = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/spidermeat= 2, /obj/item/reagent_containers/food/snacks/monstermeat/spiderleg= 8)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -53,7 +53,7 @@
icon_state = "nurse"
icon_living = "nurse"
icon_dead = "nurse_dead"
- butcher_results = list(/obj/item/reagent_containers/food/snacks/spidermeat = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8, /obj/item/reagent_containers/food/snacks/spidereggs = 4)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/spidermeat= 2, /obj/item/reagent_containers/food/snacks/monstermeat/spiderleg= 8, /obj/item/reagent_containers/food/snacks/monstermeat/spidereggs= 4)
maxHealth = 40
health = 40
diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
index ece990c7743..c093c8e3d36 100644
--- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
@@ -25,23 +25,20 @@
var/list/human_overlays = list()
/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired)
- if(!is_zombie && isturf(src.loc) && stat != DEAD)
- for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
- if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
- Zombify(H)
- break
- var/cycles = 4
- if(cycles >= 4)
- for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile
- if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD))
- visible_message("[src] consumes [target] whole!")
- if(health < maxHealth)
- health += 10
- qdel(K)
- break
- cycles = 0
- cycles++
- ..()
+ if(..() && !stat)
+ 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 || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
+ Zombify(H)
+ break
+ if(times_fired % 4 == 0)
+ for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile
+ if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD))
+ visible_message("[src] consumes [K] whole!")
+ if(health < maxHealth)
+ health += 10
+ qdel(K)
+ break
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
if(check_friendly_fire)
@@ -62,8 +59,8 @@
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
- if(A.armor && A.armor["melee"])
- maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
+ if(A.armor && A.armor.getRating("melee"))
+ maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
maxHealth += 200
health = maxHealth
name = "zombie"
@@ -93,7 +90,6 @@
if(is_zombie)
qdel(src)
-
/mob/living/simple_animal/hostile/headcrab/handle_automated_speech() // This way they have different screams when attacking, sometimes. Might be seen as sphagetthi code though.
if(speak_chance)
if(rand(0,200) < speak_chance)
@@ -106,7 +102,6 @@
M.loc = get_turf(src)
return ..()
-
/mob/living/simple_animal/hostile/headcrab/update_icons()
. = ..()
if(is_zombie)
diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm
index 801514a3256..6800598fc7f 100644
--- a/code/modules/mob/living/simple_animal/hostile/headslug.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm
@@ -72,7 +72,7 @@
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
var/mob/living/carbon/human/monkey/M = new(owner)
- owner.stomach_contents += M
+ LAZYADD(owner.stomach_contents, M)
for(var/obj/item/organ/internal/I in src)
I.insert(M, 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index d2a97949c8e..c6f3ac845e3 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -25,6 +25,7 @@
gold_core_spawnable = HOSTILE_SPAWN
loot = list(/obj/effect/decal/cleanable/blood/gibs/robot)
deathmessage = "blows apart!"
+ bubble_icon = "machine"
del_on_death = 1
/mob/living/simple_animal/hostile/hivebot/range
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index 6cde07d0b8d..469ff0cc7e1 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -79,7 +79,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum/Initialize(mapload)
. = ..()
if(true_spawn)
- for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.alive_mob_list)
if(B != src)
qdel(src) //There can be only one
return
@@ -116,8 +116,8 @@ Difficulty: Hard
if(charging)
return
- anger_modifier = Clamp(((maxHealth - health)/60),0,20)
- enrage_time = initial(enrage_time) * Clamp(anger_modifier / 20, 0.5, 1)
+ anger_modifier = clamp(((maxHealth - health)/60),0,20)
+ enrage_time = initial(enrage_time) * clamp(anger_modifier / 20, 0.5, 1)
ranged_cooldown = world.time + 50
if(client)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 7f1b3942d94..b8c72d7cf84 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -83,7 +83,7 @@ Difficulty: Very Hard
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/colossus/OpenFire()
- anger_modifier = Clamp(((maxHealth - health)/50),0,20)
+ anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + 120
if(client)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index e97b7671b67..50531f976e9 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -103,7 +103,7 @@ Difficulty: Medium
if(swooping)
return
- anger_modifier = Clamp(((maxHealth - health)/50),0,20)
+ anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + ranged_cooldown_time
if(client)
@@ -254,7 +254,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/proc/line_target(var/offset, var/range, var/atom/at = target)
if(!at)
return
- var/angle = Atan2(at.x - src.x, at.y - src.y) + offset
+ var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset
var/turf/T = get_turf(src)
for(var/i in 1 to range)
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
@@ -344,10 +344,10 @@ Difficulty: Medium
//ensure swoop direction continuity.
if(negative)
- if(IsInRange(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
+ if(ISINRANGE(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
negative = FALSE
else
- if(IsInRange(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
+ if(ISINRANGE(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
negative = TRUE
new /obj/effect/temp_visual/dragon_flight/end(loc, negative)
new /obj/effect/temp_visual/dragon_swoop(loc)
@@ -534,7 +534,7 @@ obj/effect/temp_visual/fireball
duration = 9
pixel_z = 270
-/obj/effect/temp_visual/fireball/Initialize()
+/obj/effect/temp_visual/fireball/Initialize(mapload)
. = ..()
animate(src, pixel_z = 0, time = duration)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 716f5436223..65d056188a8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -452,6 +452,7 @@ Difficulty: Hard
else
burst_range = 3
INVOKE_ASYNC(src, .proc/burst, get_turf(src), 0.25) //melee attacks on living mobs cause it to release a fast burst if on cooldown
+ OpenFire()
else
devour(L)
else
@@ -481,7 +482,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall
did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall
- anger_modifier = Clamp(((maxHealth - health) / 42),0,50)
+ anger_modifier = clamp(((maxHealth - health) / 42),0,50)
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index b3618efff0a..eed05d55e91 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -43,7 +43,6 @@
. = ..()
if(internal_type && true_spawn)
internal = new internal_type(src)
- apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
@@ -91,7 +90,7 @@
else
devour(L)
-/mob/living/simple_animal/hostile/megafauna/onShuttleMove()
+/mob/living/simple_animal/hostile/megafauna/onShuttleMove(turf/oldT, turf/T1, rotation, mob/caller)
var/turf/oldloc = loc
. = ..()
if(!.)
@@ -100,7 +99,7 @@
message_admins("Megafauna [src] \
([ADMIN_FLW(src,"FLW")]) \
moved via shuttle from ([oldloc.x], [oldloc.y], [oldloc.z]) to \
- ([newloc.x], [newloc.y], [newloc.z])")
+ ([newloc.x], [newloc.y], [newloc.z])[caller ? " called by [ADMIN_LOOKUP(caller)]" : ""]")
/mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L)
if(!L)
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index 848a285abf4..fbf65ccfa9b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -48,8 +48,8 @@
var/attempt_open = 0
// Pickup loot
-/mob/living/simple_animal/hostile/mimic/crate/Initialize()
- ..()
+/mob/living/simple_animal/hostile/mimic/crate/Initialize(mapload)
+ . = ..()
for(var/obj/item/I in loc)
I.loc = src
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
index 288d45c9b1a..d052dd9bc23 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
@@ -89,7 +89,7 @@
throw_message = "does nothing to the tough hide of the"
pre_attack_icon = "goliath2"
crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
- butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/goliath= 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
loot = list()
stat_attack = UNCONSCIOUS
robust_searching = TRUE
@@ -113,7 +113,7 @@
pre_attack_icon = "Goliath_preattack"
throw_message = "does nothing to the rocky hide of the"
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) //A throwback to the asteroid days
- butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/bone = 2)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/goliath= 2, /obj/item/stack/sheet/bone = 2)
crusher_drop_mod = 30
wander = FALSE
var/list/cached_tentacle_turfs
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
index 2f896f4adb0..fb2c741cb30 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
@@ -50,10 +50,9 @@
return ..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/regenerate_icons()
- cut_overlays()
+ ..()
if(udder.reagents.total_volume == udder.reagents.maximum_volume)
add_overlay("gl_full")
- ..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
index ca9b632e06a..a5248e98bb6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
@@ -90,6 +90,7 @@
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, .proc/death), 100)
+ AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index 7c7200e8588..a888fa7ee9a 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -23,10 +23,6 @@
var/icon_aggro = null
var/crusher_drop_mod = 25
-/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
- . = ..()
- apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
-
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range != aggro_vision_range)
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index e8ce4027b4e..89164167005 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -31,7 +31,7 @@
deathmessage = "wails as its form turns into a pulpy mush."
death_sound = 'sound/voice/hiss6.ogg'
-/mob/living/simple_animal/hostile/netherworld/migo/Initialize()
+/mob/living/simple_animal/hostile/netherworld/migo/Initialize(mapload)
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/voice/bcreep.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/mpatchedup.ogg', 'sound/voice/mfeelbetter.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heartbeat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/goonstation/effects/screech.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/goonstation/misc/airraid_loop.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/chainsaw.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshots/gunshot_silenced.ogg', 'sound/weapons/gunshots/gunshot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlock_close.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlock_open.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg', 'sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen10.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg') //hahahaha fuck you code divers
@@ -82,14 +82,14 @@
/obj/structure/spawner/nether/examine(mob/user)
. = ..()
- if(isskeleton(user) || iszombie(user))
+ if(isskeleton(user))
. += "A direct link to another dimension full of creatures very happy to see you. You can see your house from here!"
else
. += "A direct link to another dimension full of creatures not very happy to see you. Entering the link would be a very bad idea."
/obj/structure/spawner/nether/attack_hand(mob/user)
. = ..()
- if(isskeleton(user) || iszombie(user))
+ if(isskeleton(user))
to_chat(user, "You don't feel like going home yet...")
else
user.visible_message("[user] is violently pulled into the link!", \
diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
index fd569984920..07f26031ed5 100644
--- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
+++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
@@ -335,7 +335,7 @@
//Jiggle the whole worm forwards towards the next segment
-/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
if(previousWorm)
previousWorm.do_attack_animation(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index b32cae64675..105b9a02819 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -180,11 +180,11 @@
range = 10
/obj/effect/proc_holder/spell/aoe_turf/blindness/cast(list/targets, mob/user = usr)
- for(var/mob/living/L in GLOB.living_mob_list)
+ for(var/mob/living/L in GLOB.alive_mob_list)
if(L == user)
continue
var/turf/T = get_turf(L.loc)
- if(T && T in targets)
+ if(T && (T in targets))
L.EyeBlind(4)
return
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index f3389108498..decfc7146cf 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -260,7 +260,7 @@
alert_on_shield_breach = TRUE
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Initialize(mapload)
- ..()
+ . = ..()
if(prob(50))
// 50% chance of switching to extremely dangerous ranged variant
melee_damage_lower = 10
@@ -281,7 +281,7 @@
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/LateInitialize()
if(istype(depotarea))
var/list/key_candidates = list()
- for(var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O in GLOB.living_mob_list)
+ for(var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O in GLOB.alive_mob_list)
key_candidates += O
if(key_candidates.len)
var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O = pick(key_candidates)
@@ -349,7 +349,8 @@
icon = 'icons/mob/critter.dmi'
icon_state = "viscerator_attack"
icon_living = "viscerator_attack"
- pass_flags = PASSTABLE
+ pass_flags = PASSTABLE | PASSMOB
+ a_intent = INTENT_HARM
health = 15
maxHealth = 15
obj_damage = 0
@@ -362,6 +363,11 @@
minbodytemp = 0
mob_size = MOB_SIZE_TINY
flying = 1
+ bubble_icon = "syndibot"
gold_core_spawnable = HOSTILE_SPAWN
del_on_death = 1
deathmessage = "is smashed into pieces!"
+
+/mob/living/simple_animal/hostile/viscerator/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/swarming)
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
index 828e0e5f8f6..047219a151b 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
@@ -38,9 +38,12 @@
evolvequeen_action.Grant(src)
/mob/living/simple_animal/hostile/poison/terror_spider/princess/proc/evolve_to_queen()
- var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = new /mob/living/simple_animal/hostile/poison/terror_spider/queen(loc)
+ var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = new(loc)
if(mind)
mind.transfer_to(Q)
+ // Calling `transfer_to()` removes our new body (the Queen's) ability to see the med hud, so we have to re-add the queen here.
+ var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ U.add_hud_to(Q)
qdel(src)
/mob/living/simple_animal/hostile/poison/terror_spider/princess/DoWrap()
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
index 241cceb3d2c..bf3c98bb86a 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
@@ -168,7 +168,7 @@
neststep = 4
else
spider_lastspawn = world.time
- var/spiders_left_to_spawn = Clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
+ var/spiders_left_to_spawn = clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
DoLayTerrorEggs(pick(spider_types_standard), spiders_left_to_spawn)
if(4)
// Nest should be full. Otherwise, start replenishing nest (stage 5).
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 49c63b59ab5..41786017ea2 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -79,7 +79,7 @@
var/obj/desired_perches = list(/obj/structure/computerframe, /obj/structure/displaycase, \
/obj/structure/filingcabinet, /obj/machinery/teleport, \
/obj/machinery/suit_storage_unit, /obj/machinery/clonepod, \
- /obj/machinery/dna_scannernew, /obj/machinery/telecomms, \
+ /obj/machinery/dna_scannernew, /obj/machinery/tcomms, \
/obj/machinery/nuclearbomb, /obj/machinery/particle_accelerator, \
/obj/machinery/recharge_station, /obj/machinery/smartfridge, \
/obj/machinery/computer)
@@ -374,11 +374,11 @@
return
return
- if(parrot_interest && parrot_interest in view(src))
+ if(parrot_interest && (parrot_interest in view(src)))
parrot_state = PARROT_SWOOP | PARROT_STEAL
return
- if(parrot_perch && parrot_perch in view(src))
+ if(parrot_perch && (parrot_perch in view(src)))
parrot_state = PARROT_SWOOP | PARROT_RETURN
return
diff --git a/code/modules/mob/living/simple_animal/posessed_object.dm b/code/modules/mob/living/simple_animal/posessed_object.dm
index bde995d8edb..c3cb61d5970 100644
--- a/code/modules/mob/living/simple_animal/posessed_object.dm
+++ b/code/modules/mob/living/simple_animal/posessed_object.dm
@@ -27,7 +27,7 @@
. += "[src] appears to be having trouble staying afloat!"
-/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled.
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index b740c783ac7..d4f8e7c4c3d 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -144,8 +144,8 @@
/mob/living/simple_animal/updatehealth(reason = "none given")
..(reason)
- health = Clamp(health, 0, maxHealth)
- med_hud_set_status()
+ health = clamp(health, 0, maxHealth)
+ med_hud_set_health()
/mob/living/simple_animal/StartResting(updating = 1)
..()
@@ -166,12 +166,14 @@
/mob/living/simple_animal/update_stat(reason = "none given")
if(status_flags & GODMODE)
return
-
- ..(reason)
if(stat != DEAD)
- if(health < 1)
+ if(health <= 0)
death()
create_debug_log("died of damage, trigger reason: [reason]")
+ else
+ WakeUp()
+ create_debug_log("woke up, trigger reason: [reason]")
+ med_hud_set_status()
/mob/living/simple_animal/proc/handle_automated_action()
set waitfor = FALSE
@@ -594,7 +596,7 @@
toggle_ai(initial(AIStatus))
/mob/living/simple_animal/proc/add_collar(obj/item/clothing/accessory/petcollar/P, mob/user)
- if(QDELETED(P) || pcollar)
+ if(!istype(P) || QDELETED(P) || pcollar)
return
if(user && !user.unEquip(P))
return
@@ -609,7 +611,12 @@
real_name = P.tagname
/mob/living/simple_animal/regenerate_icons()
+ cut_overlays()
if(pcollar && collar_type)
- cut_overlays()
add_overlay("[collar_type]collar")
add_overlay("[collar_type]tag")
+
+/mob/living/simple_animal/Login()
+ ..()
+ walk(src, 0) // if mob is moving under ai control, then stop AI movement
+
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index d03e7ada419..4e1aee2c822 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -314,7 +314,7 @@
for(var/mob/living/L in view(7,src))
- if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
+ if(L.stat == DEAD) // Ignore dead mobs
continue
if(L in Friends) // No eating friends!
diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm
index bd9d001f12f..3f978abbfbb 100644
--- a/code/modules/mob/living/simple_animal/slime/powers.dm
+++ b/code/modules/mob/living/simple_animal/slime/powers.dm
@@ -190,7 +190,7 @@
step_away(M,src)
M.Friends = Friends.Copy()
babies += M
- M.mutation_chance = Clamp(mutation_chance+(rand(5,-5)),0,100)
+ M.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100)
feedback_add_details("slime_babies_born", "slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/simple_animal/slime/new_slime = pick(babies)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 339240af529..15f483bef76 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -17,6 +17,7 @@
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
speak_emote = list("blorbles")
+ bubble_icon = "slime"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
@@ -121,7 +122,7 @@
set_colour(pick(slime_colours))
/mob/living/simple_animal/slime/regenerate_icons()
- cut_overlays()
+ ..()
var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime"
icon_dead = "[icon_text] dead"
if(stat != DEAD)
@@ -130,7 +131,6 @@
add_overlay("aslime-[mood]")
else
icon_state = icon_dead
- ..()
/mob/living/simple_animal/slime/movement_delay()
if(bodytemperature >= 330.23) // 135 F or 57.08 C
@@ -157,7 +157,7 @@
. += config.slime_delay
-/mob/living/simple_animal/slime/handle_hud_icons_health()
+/mob/living/simple_animal/slime/update_health_hud()
if(hud_used)
if(!client)
return
@@ -262,7 +262,7 @@
Feedon(Food)
return ..()
-/mob/living/simple_animal/slime/unEquip(obj/item/I)
+/mob/living/simple_animal/slime/unEquip(obj/item/I, force)
return
/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
diff --git a/code/modules/mob/living/simple_animal/tribbles.dm b/code/modules/mob/living/simple_animal/tribbles.dm
index d5f130324bb..e5ebfb2ff61 100644
--- a/code/modules/mob/living/simple_animal/tribbles.dm
+++ b/code/modules/mob/living/simple_animal/tribbles.dm
@@ -60,7 +60,6 @@ GLOBAL_VAR_INIT(totaltribbles, 0) //global variable so it updates for all trib
/mob/living/simple_animal/tribble/proc/procreate()
- ..()
if(GLOB.totaltribbles <= maxtribbles)
for(var/mob/living/simple_animal/tribble/F in src.loc)
if(!F || F == src)
diff --git a/code/modules/mob/living/stat_states.dm b/code/modules/mob/living/stat_states.dm
index 9ff67107abd..eab88b5ec4d 100644
--- a/code/modules/mob/living/stat_states.dm
+++ b/code/modules/mob/living/stat_states.dm
@@ -7,7 +7,7 @@
else if(stat == UNCONSCIOUS)
return 0
create_attack_log("Fallen unconscious at [atom_loc_line(get_turf(src))]")
- add_attack_logs(src, null, "Fallen unconscious")
+ add_attack_logs(src, null, "Fallen unconscious", ATKLOG_ALL)
log_game("[key_name(src)] fell unconscious at [atom_loc_line(get_turf(src))]")
stat = UNCONSCIOUS
if(updating)
@@ -23,7 +23,7 @@
else if(stat == CONSCIOUS)
return 0
create_attack_log("Woken up at [atom_loc_line(get_turf(src))]")
- add_attack_logs(src, null, "Woken up")
+ add_attack_logs(src, null, "Woken up", ATKLOG_ALL)
log_game("[key_name(src)] woke up at [atom_loc_line(get_turf(src))]")
stat = CONSCIOUS
if(updating)
@@ -47,11 +47,11 @@
if(!can_be_revived())
return 0
create_attack_log("Came back to life at [atom_loc_line(get_turf(src))]")
- add_attack_logs(src, null, "Came back to life")
+ add_attack_logs(src, null, "Came back to life", ATKLOG_ALL)
log_game("[key_name(src)] came back to life at [atom_loc_line(get_turf(src))]")
stat = CONSCIOUS
GLOB.dead_mob_list -= src
- GLOB.living_mob_list += src
+ GLOB.alive_mob_list += src
if(mind)
GLOB.respawnable_list -= src
timeofdeath = null
@@ -76,4 +76,4 @@
return 1
/mob/living/proc/check_death_method()
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index b2871038155..7cd2b4414f7 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -125,10 +125,6 @@
var/stuttering = 0
var/weakened = 0
-/mob/living
- // Bitfields
- var/disabilities = 0
-
// RESTING
/mob/living/proc/StartResting(updating = 1)
@@ -467,16 +463,16 @@
// Blind
/mob/living/proc/BecomeBlind(updating = TRUE)
- var/val_change = !(disabilities & BLIND)
+ var/val_change = !(BLINDNESS in mutations)
. = val_change ? STATUS_UPDATE_BLIND : STATUS_UPDATE_NONE
- disabilities |= BLIND
+ mutations |= BLINDNESS
if(val_change && updating)
update_blind_effects()
/mob/living/proc/CureBlind(updating = TRUE)
- var/val_change = !!(disabilities & BLIND)
+ var/val_change = !!(BLINDNESS in mutations)
. = val_change ? STATUS_UPDATE_BLIND : STATUS_UPDATE_NONE
- disabilities &= ~BLIND
+ mutations -= BLINDNESS
if(val_change && updating)
CureIfHasDisability(GLOB.blindblock)
update_blind_effects()
@@ -484,52 +480,52 @@
// Coughing
/mob/living/proc/BecomeCoughing()
- disabilities |= COUGHING
+ mutations |= COUGHING
/mob/living/proc/CureCoughing()
- disabilities &= ~COUGHING
+ mutations -= COUGHING
CureIfHasDisability(GLOB.coughblock)
// Deaf
/mob/living/proc/BecomeDeaf()
- disabilities |= DEAF
+ mutations |= DEAF
/mob/living/proc/CureDeaf()
- disabilities &= ~DEAF
+ mutations -= DEAF
CureIfHasDisability(GLOB.deafblock)
// Epilepsy
/mob/living/proc/BecomeEpilepsy()
- disabilities |= EPILEPSY
+ mutations |= EPILEPSY
/mob/living/proc/CureEpilepsy()
- disabilities &= ~EPILEPSY
+ mutations -= EPILEPSY
CureIfHasDisability(GLOB.epilepsyblock)
// Mute
/mob/living/proc/BecomeMute()
- disabilities |= MUTE
+ mutations |= MUTE
/mob/living/proc/CureMute()
- disabilities &= ~MUTE
+ mutations -= MUTE
CureIfHasDisability(GLOB.muteblock)
// Nearsighted
/mob/living/proc/BecomeNearsighted(updating = TRUE)
- var/val_change = !(disabilities & NEARSIGHTED)
+ var/val_change = !(NEARSIGHTED in mutations)
. = val_change ? STATUS_UPDATE_NEARSIGHTED : STATUS_UPDATE_NONE
- disabilities |= NEARSIGHTED
+ mutations |= NEARSIGHTED
if(val_change && updating)
update_nearsighted_effects()
/mob/living/proc/CureNearsighted(updating = TRUE)
- var/val_change = !!(disabilities & NEARSIGHTED)
+ var/val_change = !!(NEARSIGHTED in mutations)
. = val_change ? STATUS_UPDATE_NEARSIGHTED : STATUS_UPDATE_NONE
- disabilities &= ~NEARSIGHTED
+ mutations -= NEARSIGHTED
if(val_change && updating)
CureIfHasDisability(GLOB.glassesblock)
update_nearsighted_effects()
@@ -537,19 +533,19 @@
// Nervous
/mob/living/proc/BecomeNervous()
- disabilities |= NERVOUS
+ mutations |= NERVOUS
/mob/living/proc/CureNervous()
- disabilities &= ~NERVOUS
+ mutations -= NERVOUS
CureIfHasDisability(GLOB.nervousblock)
// Tourettes
/mob/living/proc/BecomeTourettes()
- disabilities |= TOURETTES
+ mutations |= TOURETTES
/mob/living/proc/CureTourettes()
- disabilities &= ~TOURETTES
+ mutations -= TOURETTES
CureIfHasDisability(GLOB.twitchblock)
/mob/living/proc/CureIfHasDisability(block)
diff --git a/code/modules/mob/living/update_status.dm b/code/modules/mob/living/update_status.dm
index d24301b0dd0..8ef178918b4 100644
--- a/code/modules/mob/living/update_status.dm
+++ b/code/modules/mob/living/update_status.dm
@@ -25,7 +25,7 @@
clear_alert("high")
/mob/living/update_nearsighted_effects()
- if(disabilities & NEARSIGHTED)
+ if(NEARSIGHTED in mutations)
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("nearsighted")
@@ -41,17 +41,17 @@
// Whether the mob can hear things
/mob/living/can_hear()
- . = !(disabilities & DEAF)
+ . = !(DEAF in mutations)
// Whether the mob is able to see
// `information_only` is for stuff that's purely informational - like blindness overlays
// This flag exists because certain things like angel statues expect this to be false for dead people
/mob/living/has_vision(information_only = FALSE)
- return (information_only && stat == DEAD) || !(eye_blind || (disabilities & BLIND) || stat)
+ return (information_only && stat == DEAD) || !(eye_blind || (BLINDNESS in mutations) || stat)
// Whether the mob is capable of talking
/mob/living/can_speak()
- if(!(silent || (disabilities & MUTE)))
+ if(!(silent || (MUTE in mutations)))
if(is_muzzled())
var/obj/item/clothing/mask/muzzle/M = wear_mask
if(M.mute >= MUZZLE_MUTE_MUFFLE)
@@ -112,22 +112,6 @@
/mob/living/proc/update_stamina()
return
-/mob/living/update_stat(reason = "None given")
- if(status_flags & GODMODE)
- return
- if(stat != DEAD)
- if(health <= HEALTH_THRESHOLD_DEAD && check_death_method())
- death()
- create_debug_log("died of damage, trigger reason: [reason]")
- else if(paralysis || status_flags & FAKEDEATH)
- if(stat == CONSCIOUS)
- KnockOut()
- create_debug_log("fell unconscious, trigger reason: [reason]")
- else
- if(stat == UNCONSCIOUS)
- WakeUp()
- create_debug_log("woke up, trigger reason: [reason]")
-
/mob/living/vv_edit_var(var_name, var_value)
. = ..()
switch(var_name)
diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm
index 8bdb0d89332..91bf5f0ab9c 100644
--- a/code/modules/mob/logout.dm
+++ b/code/modules/mob/logout.dm
@@ -1,5 +1,6 @@
/mob/Logout()
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
+ SStgui.on_logout(src) // Cleanup any TGUIs the user has open
unset_machine()
GLOB.player_list -= src
log_access_out(src)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 49a4351d6cf..428e983fc2c 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1,7 +1,7 @@
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
GLOB.mob_list -= src
GLOB.dead_mob_list -= src
- GLOB.living_mob_list -= src
+ GLOB.alive_mob_list -= src
focus = null
QDEL_NULL(hud_used)
if(mind && mind.current == src)
@@ -9,9 +9,6 @@
mobspellremove(src)
QDEL_LIST(viruses)
ghostize()
- for(var/mob/dead/observer/M in following_mobs)
- M.following = null
- following_mobs = null
QDEL_LIST_ASSOC_VAL(tkgrabbed_objects)
for(var/I in tkgrabbed_objects)
qdel(tkgrabbed_objects[I])
@@ -22,18 +19,18 @@
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
AA.viewers -= src
viewing_alternate_appearances = null
- ..()
- return QDEL_HINT_HARDDEL
+ LAssailant = null
+ return ..()
-/mob/Initialize()
+/mob/Initialize(mapload)
GLOB.mob_list += src
if(stat == DEAD)
GLOB.dead_mob_list += src
else
- GLOB.living_mob_list += src
+ GLOB.alive_mob_list += src
set_focus(src)
prepare_huds()
- ..()
+ . = ..()
/atom/proc/prepare_huds()
hud_list = list()
@@ -44,6 +41,7 @@
hud_list[hud] = list()
else
var/image/I = image('icons/mob/hud.dmi', src, "")
+ I.appearance_flags = RESET_COLOR | RESET_TRANSFORM
hud_list[hud] = I
/mob/proc/generate_name()
@@ -66,8 +64,8 @@
t+= "Oxygen: [environment.oxygen] \n"
t+= "Plasma : [environment.toxins] \n"
t+= "Carbon Dioxide: [environment.carbon_dioxide] \n"
- for(var/datum/gas/trace_gas in environment.trace_gases)
- to_chat(usr, "[trace_gas.type]: [trace_gas.moles] \n")
+ t+= "N2O: [environment.sleeping_agent] \n"
+ t+= "Agent B: [environment.agent_b] \n"
usr.show_message(t, 1)
@@ -128,14 +126,12 @@
// self_message (optional) is what the src mob hears.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message)
+/mob/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
var/msg = message
for(var/mob/M in get_mobs_in_view(range, src))
- if(self_message && M == src)
- msg = self_message
M.show_message(msg, 2, deaf_message, 1)
// based on say code
@@ -157,12 +153,12 @@
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
+/atom/proc/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
for(var/mob/M in get_mobs_in_view(range, src))
- M.show_message( message, 2, deaf_message, 1)
+ M.show_message(message, 2, deaf_message, 1)
/mob/proc/findname(msg)
for(var/mob/M in GLOB.mob_list)
@@ -173,21 +169,6 @@
/mob/proc/movement_delay()
return 0
-/mob/proc/Life(seconds, times_fired)
- set waitfor = FALSE
- if(forced_look)
- if(!isnum(forced_look))
- var/atom/A = locateUID(forced_look)
- if(istype(A))
- var/view = client ? client.view : world.view
- if(get_dist(src, A) > view || !(src in viewers(view, A)))
- forced_look = null
- to_chat(src, "Your direction target has left your view, you are no longer facing anything.")
- return
- setDir()
-// handle_typing_indicator()
- return
-
//This proc is called whenever someone clicks an inventory ui slot.
/mob/proc/attack_ui(slot)
var/obj/item/W = get_active_hand()
@@ -203,10 +184,10 @@
src:update_hair()
src:update_fhair()
-/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1)
- if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob))
+/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1)
+ if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning))
return 1
- else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob))
+ else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning))
return 1
return 0
@@ -215,8 +196,7 @@
//This is a SAFE proc. Use this instead of equip_to_slot()!
//set del_on_fail to have it delete W if it fails to equip
//set disable_warning to disable the 'you are unable to equip that' warning.
-//unset redraw_mob to prevent the mob from being redrawn at the end.
-/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1)
+/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, del_on_fail = 0, disable_warning = 0)
if(!istype(W)) return 0
if(!W.mob_can_equip(src, slot, disable_warning))
@@ -228,17 +208,17 @@
return 0
- equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
+ equip_to_slot(W, slot) //This proc should not ever fail.
return 1
//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task.
//In most cases you will want to use equip_to_slot_if_possible()
-/mob/proc/equip_to_slot(obj/item/W as obj, slot)
+/mob/proc/equip_to_slot(obj/item/W, slot)
return
//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such.
/mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot)
- return equip_to_slot_if_possible(W, slot, 1, 1, 0)
+ return equip_to_slot_if_possible(W, slot, TRUE, TRUE)
// Convinience proc. Collects crap that fails to equip either onto the mob's back, or drops it.
// Used in job equipping so shit doesn't pile up at the start loc.
@@ -289,7 +269,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
for(var/slot in GLOB.slot_equipment_priority)
if(istype(W,/obj/item/storage/) && slot == slot_head) // Storage items should be put on the belt before the head
continue
- if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1
+ if(equip_to_slot_if_possible(W, slot, FALSE, TRUE)) //del_on_fail = 0; disable_warning = 0
return 1
return 0
@@ -413,8 +393,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
if(slot_w_uniform)
if( !(slot_flags & SLOT_ICLOTHING) )
return 0
- if((FAT in H.mutations) && !(flags_size & ONESIZEFITSALL))
- return 0
if(H.w_uniform)
if(!(H.w_uniform.flags & NODROP))
return 2
@@ -528,12 +506,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
update_pipe_vision()
/mob/dead/reset_perspective(atom/A)
- if(client)
- if(ismob(client.eye) && (client.eye != src))
- // Note to self: Use `client.eye` for ghost following in place
- // of periodic ghost updates
- var/mob/target = client.eye
- target.following_mobs -= src
. = ..()
if(.)
// Allows sharing HUDs with ghosts
@@ -779,7 +751,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
if(client.holder && (client.holder.rights & R_ADMIN))
is_admin = 1
- else if(stat != DEAD || istype(src, /mob/new_player))
+ else if(stat != DEAD || isnewplayer(src))
to_chat(usr, "You must be observing to use this!")
return
@@ -790,7 +762,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
var/list/namecounts = list()
var/list/creatures = list()
- for(var/obj/O in world) //EWWWWWWWWWWWWWWWWWWWWWWWW ~needs to be optimised
+ for(var/obj/O in GLOB.poi_list)
if(!O.loc)
continue
if(istype(O, /obj/item/disk/nuclear))
@@ -840,10 +812,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
if(client && mob_eye)
client.eye = mob_eye
- if(is_admin)
- client.adminobs = 1
- if(mob_eye == client.mob || client.eye == client.mob)
- client.adminobs = 0
/mob/verb/cancel_camera()
set name = "Cancel Camera View"
@@ -963,8 +931,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
for(var/obj/effect/proc_holder/spell/S in mind.spell_list)
add_spell_to_statpanel(S)
-
- if(is_admin(src))
+ // Allow admins + PR reviewers to VIEW the panel. Doesnt mean they can click things.
+ if(is_admin(src) || check_rights(R_VIEWRUNTIMES, FALSE))
if(statpanel("MC")) //looking at that panel
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
@@ -1093,7 +1061,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
if((usr in GLOB.respawnable_list) && (stat==2 || istype(usr,/mob/dead/observer)))
var/list/creatures = list("Mouse")
- for(var/mob/living/L in GLOB.living_mob_list)
+ for(var/mob/living/L in GLOB.alive_mob_list)
if(safe_respawn(L.type) && L.stat!=2)
if(!L.key)
creatures += L
@@ -1128,7 +1096,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
var/mob/living/simple_animal/mouse/host
var/obj/machinery/atmospherics/unary/vent_pump/vent_found
var/list/found_vents = list()
- for(var/obj/machinery/atmospherics/unary/vent_pump/v in world)
+ for(var/obj/machinery/atmospherics/unary/vent_pump/v in SSair.atmos_machinery)
if(!v.welded && v.z == src.z)
found_vents.Add(v)
if(found_vents.len)
@@ -1331,8 +1299,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
.["Add Organ"] = "?_src_=vars;addorgan=[UID()]"
.["Remove Organ"] = "?_src_=vars;remorgan=[UID()]"
- .["Fix NanoUI"] = "?_src_=vars;fix_nano=[UID()]"
-
.["Add Verb"] = "?_src_=vars;addverb=[UID()]"
.["Remove Verb"] = "?_src_=vars;remverb=[UID()]"
@@ -1389,6 +1355,12 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
+/mob/proc/set_sight(datum/vision_override/O)
+ QDEL_NULL(vision_type)
+ if(O) //in case of null
+ vision_type = new O
+ update_sight()
+
/mob/proc/sync_lighting_plane_alpha()
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
@@ -1416,3 +1388,29 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
///Force set the mob nutrition
/mob/proc/set_nutrition(change)
nutrition = max(0, change)
+
+/mob/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
+ . = ..()
+ if(bloody_hands && clean_hands)
+ bloody_hands = 0
+ update_inv_gloves()
+ if(l_hand)
+ if(l_hand.clean_blood())
+ update_inv_l_hand()
+ if(r_hand)
+ if(r_hand.clean_blood())
+ update_inv_r_hand()
+ if(back)
+ if(back.clean_blood())
+ update_inv_back()
+ if(wear_mask && clean_mask)
+ if(wear_mask.clean_blood())
+ update_inv_wear_mask()
+ if(clean_feet)
+ feet_blood_color = null
+ qdel(feet_blood_DNA)
+ bloody_feet = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0)
+ blood_state = BLOOD_STATE_NOT_BLOODY
+ update_inv_shoes()
+ update_icons() //apply the now updated overlays to the mob
+
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index cea1e59ceb9..80404460b50 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -31,8 +31,8 @@
var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot
var/damageoverlaytemp = 0
var/computer_id = null
- var/lastattacker = null
- var/lastattacked = null
+ var/lastattacker = null // real name of the person doing the attacking
+ var/lastattackerckey = null // their ckey
var/list/attack_log_old = list( )
var/list/debug_log = null
@@ -44,14 +44,12 @@
var/memory = ""
var/next_move = null
var/notransform = null //Carbon
- var/other = 0.0
var/hand = null
var/real_name = null
var/flavor_text = ""
var/med_record = ""
var/sec_record = ""
var/gen_record = ""
- var/bhunger = 0 //Carbon
var/lying = 0
var/lying_prev = 0
var/lastpuke = 0
@@ -62,36 +60,31 @@
var/emote_type = 1 // Define emote default type, 1 for seen emotes, 2 for heard emotes
var/name_archive //For admin things like possession
- var/timeofdeath = 0.0//Living
- var/cpr_time = 1.0//Carbon
-
+ var/timeofdeath = 0 //Living
var/bodytemperature = 310.055 //98.7 F
var/flying = 0
- var/charges = 0.0
var/nutrition = NUTRITION_LEVEL_FED + 50 //Carbon
var/satiety = 0 //Carbon
var/hunger_drain = HUNGER_FACTOR // how quickly the mob gets hungry; largely utilized by species.
var/overeatduration = 0 // How long this guy is overeating //Carbon
- var/intent = null//Living
+ var/intent = null //Living
var/shakecamera = 0
- var/a_intent = INTENT_HELP//Living
- var/m_intent = MOVE_INTENT_RUN//Living
+ var/a_intent = INTENT_HELP //Living
+ var/m_intent = MOVE_INTENT_RUN //Living
var/lastKnownIP = null
/// movable atoms buckled to this mob
- var/atom/movable/buckled = null//Living
+ var/atom/movable/buckled = null //Living
/// movable atom we are buckled to
var/atom/movable/buckling
- var/obj/item/l_hand = null//Living
- var/obj/item/r_hand = null//Living
- var/obj/item/back = null//Human/Monkey
- var/obj/item/tank/internal = null//Human/Monkey
- var/obj/item/storage/s_active = null//Carbon
- var/obj/item/clothing/mask/wear_mask = null//Carbon
-
- var/seer = 0 //for cult//Carbon, probably Human
+ var/obj/item/l_hand = null //Living
+ var/obj/item/r_hand = null //Living
+ var/obj/item/back = null //Human
+ var/obj/item/tank/internal = null //Human
+ var/obj/item/storage/s_active = null //Carbon
+ var/obj/item/clothing/mask/wear_mask = null //Carbon
var/datum/hud/hud_used = null
@@ -100,7 +93,6 @@
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
var/list/grabbed_by = list()
- var/list/requests = list()
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
var/list/mapobjs = list()
@@ -108,9 +100,9 @@
var/emote_cd = 0 // Used to supress emote spamming. 1 if on CD, 2 if disabled by admin (manually set), else 0
- var/job = null//Living
+ var/job = null //Living
- var/datum/dna/dna = null//Carbon
+ var/datum/dna/dna = null //Carbon
var/radiation = 0 //Carbon
var/list/mutations = list() //Carbon -- Doohl
@@ -165,10 +157,7 @@
var/atom/movable/remote_control //Calls relaymove() to whatever it is
- var/remote_view = 0 // Set to 1 to prevent view resets on Life
-
var/obj/control_object //Used by admins to possess objects. All mobs should have this var
- var/datum/visibility_interface/visibility_interface = null // used by the visibility system to provide an interface for the visibility networks
//Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything.
var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE
@@ -187,8 +176,6 @@
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
- var/kills = 0
-
var/stance_damage = 0 //Whether this mob's ability to stand has been affected
var/list/active_genes = list()
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index f595f6b4839..37e116b4376 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -53,12 +53,11 @@
hud.master = src
//check if assailant is grabbed by victim as well
- if(assailant.grabbed_by)
- for(var/obj/item/grab/G in assailant.grabbed_by)
- if(G.assailant == affecting && G.affecting == assailant)
- G.dancing = 1
- G.adjust_position()
- dancing = 1
+ for(var/obj/item/grab/G in assailant.grabbed_by)
+ if(G.assailant == affecting && G.affecting == assailant)
+ G.dancing = 1
+ G.adjust_position()
+ dancing = 1
clean_grabbed_by(assailant, affecting)
adjust_position()
@@ -276,7 +275,7 @@
assailant.visible_message("[assailant] has reinforced [assailant.p_their()] grip on [affecting] (now neck)!")
state = GRAB_NECK
icon_state = "grabbed+1"
- assailant.setDir(get_dir(assailant, affecting))
+
add_attack_logs(assailant, affecting, "Neck grabbed", ATKLOG_ALL)
if(!iscarbon(assailant))
affecting.LAssailant = null
@@ -296,7 +295,7 @@
assailant.next_move = world.time + 10
if(!affecting.get_organ_slot("breathing_tube"))
affecting.AdjustLoseBreath(1)
- affecting.setDir(WEST)
+
adjust_position()
//This is used to make sure the victim hasn't managed to yackety sax away before using the grab.
@@ -409,7 +408,7 @@
add_attack_logs(attacker, affecting, "Devoured")
affecting.forceMove(user)
- attacker.stomach_contents.Add(affecting)
+ LAZYADD(attacker.stomach_contents, affecting)
qdel(src)
/obj/item/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
@@ -433,9 +432,10 @@
/obj/item/grab/Destroy()
if(affecting)
- affecting.pixel_x = 0
- affecting.pixel_y = 0 //used to be an animate, not quick enough for del'ing
- affecting.layer = initial(affecting.layer)
+ if(!affecting.buckled)
+ affecting.pixel_x = 0
+ affecting.pixel_y = 0 //used to be an animate, not quick enough for qdel'ing
+ affecting.layer = initial(affecting.layer)
affecting.grabbed_by -= src
affecting = null
if(assailant)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 1e0f31ac6fe..5fb5bcb06c8 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -12,14 +12,6 @@
return 1
return 0
-/mob/proc/isSynthetic()
- return 0
-
-/mob/living/carbon/human/isSynthetic()
- if(ismachine(src))
- return TRUE
- return FALSE
-
/mob/proc/get_screen_colour()
/mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length.
@@ -467,7 +459,7 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
name = realname
for(var/mob/M in GLOB.player_list)
- if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(CHAT_DEAD))
+ if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(CHAT_DEAD))
var/follow
var/lname
if(subject)
@@ -521,11 +513,11 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
alert_overlay.plane = FLOAT_PLANE
A.overlays += alert_overlay
-/mob/proc/switch_to_camera(var/obj/machinery/camera/C)
- if(!C.can_use() || stat || (get_dist(C, src) > 1 || machine != src || !has_vision() || !canmove))
- return 0
+/mob/proc/switch_to_camera(obj/machinery/camera/C)
+ if(!C.can_use() || incapacitated() || (get_dist(C, src) > 1 || machine != src || !has_vision()))
+ return FALSE
check_eye(src)
- return 1
+ return TRUE
/mob/proc/rename_character(oldname, newname)
if(!newname)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 8fb7568cefd..4797c685fe1 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -26,25 +26,6 @@
else
to_chat(usr, "This mob type cannot throw items.")
-
-/client/verb/drop_item()
- set hidden = 1
- if(!isrobot(mob))
- mob.drop_item_v()
- return
-
-
-/* /client/Center()
- /* No 3D movement in 2D spessman game. dir 16 is Z Up
- if(isobj(mob.loc))
- var/obj/O = mob.loc
- if(mob.canmove)
- return O.relaymove(mob, 16)
- */
- return
- */
-
-
/client/proc/Move_object(direct)
if(mob && mob.control_object)
if(mob.control_object.density)
@@ -143,8 +124,10 @@
move_delay = world.time
mob.last_movement = world.time
+ delay = TICKS2DS(-round(-(DS2TICKS(delay)))) //Rounded to the next tick in equivalent ds
+
if(locate(/obj/item/grab, mob))
- move_delay = max(move_delay, world.time + 7)
+ delay += 7
var/list/L = mob.ret_grab()
if(istype(L, /list))
if(L.len == 2)
@@ -153,14 +136,14 @@
if(M)
if((get_dist(mob, M) <= 1 || M.loc == mob.loc))
var/turf/prev_loc = mob.loc
- . = ..()
+ . = mob.SelfMove(n, direct, delay)
if(M && isturf(M.loc)) // Mob may get deleted during parent call
var/diag = get_dir(mob, M)
if((diag - 1) & diag)
else
diag = null
if((get_dist(mob, M) > 1 || diag))
- step(M, get_dir(M.loc, prev_loc))
+ M.Move(prev_loc, get_dir(M.loc, prev_loc), delay)
else
for(var/mob/M in L)
M.other_mobs = 1
@@ -168,12 +151,10 @@
M.animate_movement = 3
for(var/mob/M in L)
spawn(0)
- step(M, direct)
- return
+ M.Move(get_step(M,direct), direct, delay)
spawn(1)
M.other_mobs = null
M.animate_movement = 2
- return
else if(mob.confused)
var/newdir = 0
@@ -187,18 +168,21 @@
direct = newdir
n = get_step(mob, direct)
- . = ..()
+ . = mob.SelfMove(n, direct, delay)
mob.setDir(direct)
+ if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
+ delay = mob.movement_delay() * 2 //Will prevent mob diagonal moves from smoothing accurately, sadly
+
+ move_delay += delay
+
for(var/obj/item/grab/G in mob)
if(G.state == GRAB_NECK)
mob.setDir(angle2dir((dir2angle(direct) + 202.5) % 365))
G.adjust_position()
for(var/obj/item/grab/G in mob.grabbed_by)
G.adjust_position()
- if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
- delay = mob.movement_delay() * 2
- move_delay += delay
+
moving = 0
if(mob && .)
if(mob.throwing)
@@ -208,8 +192,8 @@
O.on_mob_move(direct, mob)
-
-
+/mob/proc/SelfMove(turf/n, direct, movetime)
+ return Move(n, direct, movetime)
///Process_Grab()
///Called by client/Move()
diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm
index c3ec68c9793..1e704ea3449 100644
--- a/code/modules/mob/mob_transformation_simple.dm
+++ b/code/modules/mob/mob_transformation_simple.dm
@@ -4,7 +4,7 @@
//Note that this proc does NOT do MMI related stuff!
/mob/proc/change_mob_type(var/new_type = null, var/turf/location = null, var/new_name = null as text, var/delete_old_mob = 0 as num, var/forcekey = 0)
- if(istype(src,/mob/new_player))
+ if(isnewplayer(src))
to_chat(usr, "cannot convert players who have not entered yet.")
return
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 89e6ce953f5..f53daba6626 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -12,8 +12,13 @@
stat = 2
canmove = 0
-/mob/new_player/New()
+/mob/new_player/Initialize(mapload)
+ SHOULD_CALL_PARENT(FALSE)
+ if(initialized)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ initialized = TRUE
GLOB.mob_list += src
+ return INITIALIZE_HINT_NORMAL
/mob/new_player/verb/new_player_panel()
set src = usr
@@ -205,6 +210,7 @@
if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
observer.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
observer.key = key
+ QDEL_NULL(mind)
GLOB.respawnable_list += observer
qdel(src)
return 1
@@ -384,7 +390,7 @@
if(GLOB.summon_magic_triggered)
give_magic(character)
- if(!thisjob.is_position_available() && thisjob in SSjobs.prioritized_jobs)
+ if(!thisjob.is_position_available() && (thisjob in SSjobs.prioritized_jobs))
SSjobs.prioritized_jobs -= thisjob
qdel(src)
@@ -392,7 +398,7 @@
/mob/new_player/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message)
if(SSticker.current_state == GAME_STATE_PLAYING)
var/ailist[] = list()
- for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
ailist += A
if(ailist.len)
var/mob/living/silicon/ai/announcer = pick(ailist)
@@ -424,7 +430,7 @@
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message)
if(SSticker.current_state == GAME_STATE_PLAYING)
var/ailist[] = list()
- for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list)
ailist += A
if(ailist.len)
var/mob/living/silicon/ai/announcer = pick(ailist)
diff --git a/code/modules/mob/new_player/poll.dm b/code/modules/mob/new_player/poll.dm
index 8a9b71426b8..2e109d36d34 100644
--- a/code/modules/mob/new_player/poll.dm
+++ b/code/modules/mob/new_player/poll.dm
@@ -42,8 +42,8 @@
// Show expired polls. Non admins can view admin polls at this stage
// (just like tgstation's web interface so don't complain)
- // (Also why was there no ingame interface tg not having an ingame
- // interface is retarded because it cucks downstreams)
+ // (Also why was there no ingame interface? tg not having an ingame
+ // interface is a pain in the neck because it means downstreams have to roll their own)
select_query = GLOB.dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() > endtime ORDER BY id DESC")
select_query.Execute()
@@ -90,9 +90,9 @@
if(adminonly)
question = "(Admin only poll) " + question
- var output = ""
+ var/output = ""
if(polltype == POLLTYPE_MULTI || polltype == POLLTYPE_OPTION)
- select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]");
+ select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
select_query.Execute()
var/list/options = list()
var/total_votes = 1
@@ -177,7 +177,7 @@
output += "
"
output += ""
if(polltype == POLLTYPE_TEXT)
- select_query = GLOB.dbcon.NewQuery("SELECT replytext, COUNT(replytext) AS countresponse, GROUP_CONCAT(DISTINCT ckey SEPARATOR ', ') as ckeys FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] GROUP BY replytext ORDER BY countresponse DESC");
+ select_query = GLOB.dbcon.NewQuery("SELECT replytext, COUNT(replytext) AS countresponse, GROUP_CONCAT(DISTINCT ckey SEPARATOR ', ') as ckeys FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] GROUP BY replytext ORDER BY countresponse DESC")
select_query.Execute()
output += {"
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index 8324ef87212..77f8cc40da9 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -237,10 +237,7 @@
else
icobase = 'icons/mob/human_races/r_human.dmi'
- var/fat=""
- if(disabilities & DISABILITY_FLAG_FAT && (CAN_BE_FAT in current_species.species_traits))
- fat="_fat"
- preview_icon = new /icon(icobase, "torso_[g][fat]")
+ preview_icon = new /icon(icobase, "torso_[g]")
preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY)
var/head = "head"
if(alt_head && current_species.bodyflags & HAS_ALT_HEADS)
@@ -404,8 +401,6 @@
var/icon/clothes_s = null
var/uniform_dmi='icons/mob/uniform.dmi'
- if(disabilities&DISABILITY_FLAG_FAT)
- uniform_dmi='icons/mob/uniform_fat.dmi'
if(job_support_low & JOB_CIVILIAN)//This gives the preview icon clothes depending on which job(if any) is set to 'high'
clothes_s = new /icon(uniform_dmi, "grey_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
@@ -926,7 +921,7 @@
if(4)
clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY)
- if(disabilities & NEARSIGHTED)
+ if(disabilities & DISABILITY_FLAG_NEARSIGHTED)
preview_icon.Blend(new /icon('icons/mob/eyes.dmi', "glasses"), ICON_OVERLAY)
// Observers get tourist outfit.
diff --git a/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm b/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm
index f9e1ee1cc49..0dd6910e591 100644
--- a/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm
+++ b/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm
@@ -200,7 +200,7 @@
name = "Emo"
icon_state = "emo"
-/datum/sprite_accessory/hair/fag
+/datum/sprite_accessory/hair/flow
name = "Flow Hair"
icon_state = "flow"
diff --git a/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm b/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm
index 8910a8f5229..6868521f9c2 100644
--- a/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm
+++ b/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm
@@ -4,6 +4,10 @@
glasses_over = 1
models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.", "Shellguard Munitions Monitor Series")
+/datum/sprite_accessory/hair/ipc/ipc_screen_blank
+ name = "Blank IPC Screen"
+ icon_state = "blank"
+
/datum/sprite_accessory/hair/ipc/ipc_screen_pink
name = "Pink IPC Screen"
icon_state = "pink"
diff --git a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
index 476861861a3..d4834eccc80 100644
--- a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
@@ -48,7 +48,7 @@
var/gender = NEUTER //Determines if the accessory will be skipped or included in random hair generations
// Restrict some styles to specific species
- var/list/species_allowed = list("Human", "Slime People", "Infectious Zombie", "High-Functioning Zombie")
+ var/list/species_allowed = list("Human", "Slime People")
var/list/sprite_sheets = list() //For accessories common across species but need to use 'fitted' sprites (like underwear). e.g. list("Vox" = 'icons/mob/species/vox/iconfile.dmi')
var/list/models_allowed = list() //Specifies which, if any, hairstyles or markings can be accessed by which prosthetics. Should equal the manufacturing company name in robolimbs.dm.
var/list/heads_allowed = null //Specifies which, if any, alt heads a head marking, hairstyle or facial hair style is compatible with.
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 49b188a4365..41032185c3b 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -115,7 +115,7 @@
return get_turf(src)
-/mob/proc/say_test(var/text)
+/proc/say_test(text)
var/ending = copytext(text, length(text))
if(ending == "?")
return "1"
diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm
index b61ce171194..3a053e74e16 100644
--- a/code/modules/mob/status_procs.dm
+++ b/code/modules/mob/status_procs.dm
@@ -207,4 +207,4 @@
/mob/proc/adjust_bodytemperature(amount, min_temp = 0, max_temp = INFINITY)
if(bodytemperature >= min_temp && bodytemperature <= max_temp)
- bodytemperature = Clamp(bodytemperature + amount, min_temp, max_temp)
+ bodytemperature = clamp(bodytemperature + amount, min_temp, max_temp)
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 2ee4a9d2a9c..8e7adea666b 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -82,14 +82,11 @@
O.notify_ai(1)
if(O.mind && O.mind.assigned_role == "Cyborg")
- if(O.mind.role_alt_title == "Android")
+ if(O.mind.role_alt_title == "Robot")
O.mmi = new /obj/item/mmi/robotic_brain(O)
- else if(O.mind.role_alt_title == "Robot")
- O.mmi = null //Robots do not have removable brains.
else
O.mmi = new /obj/item/mmi(O)
-
- if(O.mmi) O.mmi.transfer_identity(src) //Does not transfer key/client.
+ O.mmi.transfer_identity(src) //Does not transfer key/client.
O.update_pipe_vision()
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index 7b13ab68229..a2ca226147c 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -5,31 +5,32 @@ mob/var/typing
mob/var/last_typed
mob/var/last_typed_time
-GLOBAL_DATUM(typing_indicator, /image)
+GLOBAL_LIST_EMPTY(typing_indicator)
-/mob/proc/set_typing_indicator(var/state)
+/mob/proc/set_typing_indicator(state)
- if(!GLOB.typing_indicator)
- GLOB.typing_indicator = image('icons/mob/talk.dmi', null, "typing", MOB_LAYER + 1)
- GLOB.typing_indicator.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
+ if(!GLOB.typing_indicator[bubble_icon])
+ GLOB.typing_indicator[bubble_icon] = image('icons/mob/talk.dmi', null, "[bubble_icon]typing", FLY_LAYER)
+ var/image/I = GLOB.typing_indicator[bubble_icon]
+ I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
if(ishuman(src))
var/mob/living/carbon/human/H = src
- if(H.disabilities & MUTE || H.silent)
- overlays -= GLOB.typing_indicator
+ if((MUTE in H.mutations) || H.silent)
+ overlays -= GLOB.typing_indicator[bubble_icon]
return
if(client)
if((client.prefs.toggles & SHOW_TYPING) || stat != CONSCIOUS || is_muzzled())
- overlays -= GLOB.typing_indicator
+ overlays -= GLOB.typing_indicator[bubble_icon]
else
if(state)
if(!typing)
- overlays += GLOB.typing_indicator
+ overlays += GLOB.typing_indicator[bubble_icon]
typing = 1
else
if(typing)
- overlays -= GLOB.typing_indicator
+ overlays -= GLOB.typing_indicator[bubble_icon]
typing = 0
return state
diff --git a/code/modules/modular_computers/NTNet/NTNet_relay.dm b/code/modules/modular_computers/NTNet/NTNet_relay.dm
index c0cc534ea0b..97ddcfb69c0 100644
--- a/code/modules/modular_computers/NTNet/NTNet_relay.dm
+++ b/code/modules/modular_computers/NTNet/NTNet_relay.dm
@@ -3,7 +3,7 @@
name = "NTNet Quantum Relay"
desc = "A very complex router and transmitter capable of connecting electronic devices together. Looks fragile."
use_power = ACTIVE_POWER_USE
- active_power_usage = 10000 //10kW, apropriate for machine that keeps massive cross-Zlevel wireless network operational. Used to be 20 but that actually drained the smes one round
+ active_power_usage = 100 // 100 watts. Yes I know this is a high power machine but this fucking obliterates an unpowered smes (AI sat)
idle_power_usage = 100
icon = 'icons/obj/stationobjs.dmi'
icon_state = "bus"
@@ -99,7 +99,6 @@
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/ntnet_relay(null)
component_parts += new /obj/item/stack/cable_coil(null, 2)
- component_parts += new /obj/item/stock_parts/subspace/filter(null)
if(GLOB.ntnet_global)
GLOB.ntnet_global.relays.Add(src)
@@ -123,6 +122,4 @@
name = "NTNet Relay (Machine Board)"
build_path = /obj/machinery/ntnet_relay
origin_tech = "programming=3;bluespace=3;magnets=2"
- req_components = list(
- /obj/item/stack/cable_coil = 2,
- /obj/item/stock_parts/subspace/filter = 1)
+ req_components = list(/obj/item/stack/cable_coil = 2)
diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm
index 7b025087a8b..223627bd69e 100644
--- a/code/modules/modular_computers/computers/item/laptop.dm
+++ b/code/modules/modular_computers/computers/item/laptop.dm
@@ -89,11 +89,13 @@
/obj/item/modular_computer/laptop/proc/toggle_open(mob/living/user=null)
if(screen_on)
- to_chat(user, "You close \the [src].")
+ if(user)
+ to_chat(user, "You close \the [src].")
slowdown = initial(slowdown)
w_class = initial(w_class)
else
- to_chat(user, "You open \the [src].")
+ if(user)
+ to_chat(user, "You open \the [src].")
slowdown = slowdown_open
w_class = w_class_open
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 7bd5be3cf81..3095e0af876 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -19,7 +19,6 @@
/obj/item/modular_computer/processor/New(comp)
if(!comp || !istype(comp, /obj/machinery/modular_computer))
CRASH("Inapropriate type passed to obj/item/modular_computer/processor/New()! Aborting.")
- return
// Obtain reference to machinery computer
all_components = list()
idle_threads = list()
diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm
index 9067a345d4e..b85fb710e38 100644
--- a/code/modules/modular_computers/file_system/programs/command/card.dm
+++ b/code/modules/modular_computers/file_system/programs/command/card.dm
@@ -35,7 +35,8 @@
/datum/job/ntnavyofficer,
/datum/job/ntspecops,
/datum/job/civilian,
- /datum/job/syndicateofficer
+ /datum/job/syndicateofficer,
+ /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work
)
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
diff --git a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm
index 379e71ba484..0045b36f30e 100644
--- a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm
@@ -84,9 +84,7 @@
data["SM_ambienttemp"] = air.temperature
data["SM_ambientpressure"] = air.return_pressure()
//data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01)
- var/other_moles = 0.0
- for(var/datum/gas/G in air.trace_gases)
- other_moles+=G.moles
+ var/other_moles = air.total_trace_moles()
var/TM = air.total_moles()
if(TM)
data["SM_gas_O2"] = round(100*air.oxygen/TM,0.01)
@@ -94,7 +92,7 @@
data["SM_gas_N2"] = round(100*air.nitrogen/TM,0.01)
data["SM_gas_PL"] = round(100*air.toxins/TM,0.01)
if(other_moles)
- data["SM_gas_OTHER"] = round(100*other_moles/TM,0.01)
+ data["SM_gas_OTHER"] = round(100 * other_moles / TM, 0.01)
else
data["SM_gas_OTHER"] = 0
else
diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
index 517c8f99ebe..ca208c22b02 100644
--- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
@@ -195,7 +195,6 @@
if(!computer)
// This program shouldn't even be runnable without computer.
CRASH("Var computer is null!")
- return 1
if(!hard_drive)
computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.")
else // In 99.9% cases this will mean our HDD is full
diff --git a/code/modules/modular_computers/file_system/programs/research/airestorer.dm b/code/modules/modular_computers/file_system/programs/research/airestorer.dm
index d5ff31af66b..a87a2cd87b4 100644
--- a/code/modules/modular_computers/file_system/programs/research/airestorer.dm
+++ b/code/modules/modular_computers/file_system/programs/research/airestorer.dm
@@ -78,7 +78,7 @@
A.stat = CONSCIOUS
A.lying = 0
GLOB.dead_mob_list -= A
- GLOB.living_mob_list += A
+ GLOB.alive_mob_list += A
// Finished restoring
if(A.health >= 100)
ai_slot.locked = FALSE
diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm
index 7cec597dc13..1a48110006a 100644
--- a/code/modules/modular_computers/hardware/battery_module.dm
+++ b/code/modules/modular_computers/hardware/battery_module.dm
@@ -67,7 +67,6 @@
holder.shutdown_computer()
return TRUE
- return FALSE
// Stock parts
diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm
index ca42220204d..fed18f989f5 100644
--- a/code/modules/nano/interaction/default.dm
+++ b/code/modules/nano/interaction/default.dm
@@ -85,7 +85,7 @@ GLOBAL_DATUM_INIT(default_state, /datum/topic_state/default, new())
if(. != STATUS_CLOSE)
if(loc)
. = min(., loc.contents_nano_distance(src_object, src))
- if(STATUS_INTERACTIVE)
+ if(. == STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/brain/default_can_use_topic(var/src_object)
diff --git a/code/modules/nano/modules/atmos_control.dm b/code/modules/nano/modules/atmos_control.dm
index 76d14bb3e00..2c74a1ce844 100644
--- a/code/modules/nano/modules/atmos_control.dm
+++ b/code/modules/nano/modules/atmos_control.dm
@@ -12,7 +12,7 @@
if(monitored_alarm_ids)
for(var/obj/machinery/alarm/alarm in GLOB.machines)
- if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids)
+ if(alarm.alarm_id && (alarm.alarm_id in monitored_alarm_ids))
monitored_alarms += alarm
// machines may not yet be ordered at this point
monitored_alarms = dd_sortedObjectList(monitored_alarms)
diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm
deleted file mode 100644
index 4ed7fc03de1..00000000000
--- a/code/modules/nano/modules/crew_monitor.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-/datum/nano_module/crew_monitor
- name = "Crew monitor"
-
-/datum/nano_module/crew_monitor/Topic(href, href_list)
- if(..())
- return 1
- var/turf/T = get_turf(nano_host())
- if(!T || !is_level_reachable(T.z))
- to_chat(usr, "Unable to establish a connection: You're too far away from the station!")
- return 0
- if(href_list["track"])
- if(isAI(usr))
- var/mob/living/silicon/ai/AI = usr
- var/mob/living/carbon/human/H = locate(href_list["track"]) in GLOB.mob_list
- if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
- AI.ai_actual_track(H)
- return 1
-
-/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
-
- // adding a template with the key "mapContent" enables the map ui functionality
- ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
- // adding a template with the key "mapHeader" replaces the map header content
- ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
-
- ui.open()
-
- // should make the UI auto-update; doesn't seem to?
- ui.set_auto_update(1)
-
-/datum/nano_module/crew_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
- var/data[0]
- var/turf/T = get_turf(nano_host())
-
- data["isAI"] = isAI(user)
- data["crewmembers"] = GLOB.crew_repository.health_data(T)
-
- return data
diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm
index f2423e57c2f..64850ea954d 100644
--- a/code/modules/nano/modules/law_manager.dm
+++ b/code/modules/nano/modules/law_manager.dm
@@ -99,7 +99,7 @@
if(href_list["change_supplied_law_position"])
var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null
if(isnum(new_position) && can_still_topic())
- supplied_law_position = Clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
+ supplied_law_position = clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
return 1
if(href_list["edit_law"])
diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm
index 602a46dbfa3..f57014496fd 100644
--- a/code/modules/nano/nanoexternal.dm
+++ b/code/modules/nano/nanoexternal.dm
@@ -37,7 +37,7 @@
*
* @return nothing
*/
-/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
+/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
return
/**
diff --git a/code/modules/nano/nanomapgen.dm b/code/modules/nano/nanomapgen.dm
deleted file mode 100644
index be9c5bbe2b3..00000000000
--- a/code/modules/nano/nanomapgen.dm
+++ /dev/null
@@ -1,90 +0,0 @@
-// This file is a modified version of https://raw2.github.com/Baystation12/OldCode-BS12/master/code/TakePicture.dm
-
-#define NANOMAP_ICON_SIZE 4
-#define NANOMAP_MAX_ICON_DIMENSION 1024
-
-#define NANOMAP_TILES_PER_IMAGE (NANOMAP_MAX_ICON_DIMENSION / NANOMAP_ICON_SIZE)
-
-#define NANOMAP_TERMINALERR 5
-#define NANOMAP_INPROGRESS 2
-#define NANOMAP_BADOUTPUT 2
-#define NANOMAP_SUCCESS 1
-#define NANOMAP_WATCHDOGSUCCESS 4
-#define NANOMAP_WATCHDOGTERMINATE 3
-
-
-//Call these procs to dump your world to a series of image files (!!)
-//NOTE: Does not explicitly support non 32x32 icons or stuff with large pixel_* values, so don't blame me if it doesn't work perfectly
-
-/client/proc/nanomapgen_DumpImage()
- set name = "Generate NanoUI Map"
- set category = "Mapping"
-
- if(holder)
- nanomapgen_DumpTile(1, 1, text2num(input(usr,"Enter the Z level to generate")))
-
-/client/proc/nanomapgen_DumpTile(var/startX = 1, var/startY = 1, var/currentZ = 1, var/endX = -1, var/endY = -1)
-
- if(endX < 0 || endX > world.maxx)
- endX = world.maxx
-
- if(endY < 0 || endY > world.maxy)
- endY = world.maxy
-
- if(currentZ < 0 || currentZ > world.maxz)
- to_chat(usr, "NanoMapGen: ERROR: currentZ ([currentZ]) must be between 1 and [world.maxz]")
-
- sleep(3)
- return NANOMAP_TERMINALERR
-
- if(startX > endX)
- to_chat(usr, "NanoMapGen: ERROR: startX ([startX]) cannot be greater than endX ([endX])")
-
- sleep(3)
- return NANOMAP_TERMINALERR
-
- if(startY > endX)
- to_chat(usr, "NanoMapGen: ERROR: startY ([startY]) cannot be greater than endY ([endY])")
- sleep(3)
- return NANOMAP_TERMINALERR
-
- var/icon/Tile = icon(file("nano/mapbase1024.png"))
- if(Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION)
- log_world("NanoMapGen: ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]")
- sleep(3)
- return NANOMAP_TERMINALERR
-
- log_world("NanoMapGen: GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])")
- to_chat(usr, "NanoMapGen: GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])")
-
- var/count = 0;
- for(var/WorldX = startX, WorldX <= endX, WorldX++)
- for(var/WorldY = startY, WorldY <= endY, WorldY++)
-
- var/atom/Turf = locate(WorldX, WorldY, currentZ)
-
- var/icon/TurfIcon = new(Turf.icon, Turf.icon_state)
- TurfIcon.Scale(NANOMAP_ICON_SIZE, NANOMAP_ICON_SIZE)
-
- Tile.Blend(TurfIcon, ICON_OVERLAY, ((WorldX - 1) * NANOMAP_ICON_SIZE), ((WorldY - 1) * NANOMAP_ICON_SIZE))
-
- count++
-
- if(count % 8000 == 0)
- log_world("NanoMapGen: [count] tiles done")
- sleep(1)
-
- var/mapFilename = "nanomap_z[currentZ]-new.png"
-
- log_world("NanoMapGen: sending [mapFilename] to client")
-
- usr << browse(Tile, "window=picture;file=[mapFilename];display=0")
-
- log_world("NanoMapGen: Done.")
-
- to_chat(usr, "NanoMapGen: Done. File [mapFilename] uploaded to your cache.")
-
- if(Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION)
- return NANOMAP_BADOUTPUT
-
- return NANOMAP_SUCCESS
diff --git a/code/modules/nano/subsystem.dm b/code/modules/nano/subsystem.dm
index 6ad4201b93d..f2f86c02a3c 100644
--- a/code/modules/nano/subsystem.dm
+++ b/code/modules/nano/subsystem.dm
@@ -163,7 +163,7 @@
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list())
else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
- open_uis[src_object_key][ui.ui_key] = list();
+ open_uis[src_object_key][ui.ui_key] = list()
ui.user.open_uis.Add(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm
index cf694e59d83..741f0399922 100644
--- a/code/modules/ninja/energy_katana.dm
+++ b/code/modules/ninja/energy_katana.dm
@@ -52,7 +52,7 @@
if(user.put_in_hands(src))
msg = "Your Energy Katana teleports into your hand!"
- else if(user.equip_to_slot_if_possible(src, slot_belt, 0, 1, 1))
+ else if(user.equip_to_slot_if_possible(src, slot_belt, FALSE, TRUE))
msg = "Your Energy Katana teleports back to you, sheathing itself as it does so!"
else
loc = get_turf(user)
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 626a3d99e59..eb350f5e29a 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -135,7 +135,6 @@
P.name = "paper - '[G.fields["name"]]'"
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
- ..()
/obj/structure/filingcabinet/security/attack_hand()
populate()
@@ -169,7 +168,6 @@
P.name = "paper - '[G.fields["name"]]'"
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
- ..()
/obj/structure/filingcabinet/medical/attack_hand()
populate()
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index de894e80106..eefb4d299a4 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -7,6 +7,12 @@
pressure_resistance = 2
resistance_flags = FLAMMABLE
+/obj/item/folder/emp_act(severity)
+ ..()
+ for(var/i in contents)
+ var/atom/A = i
+ A.emp_act(severity)
+
/obj/item/folder/blue
desc = "A blue folder."
icon_state = "folder_blue"
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index 74bee9867ab..7722dd2b53f 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -1,11 +1,12 @@
/obj/item/hand_labeler
name = "hand labeler"
+ desc = "A combined label printer, applicator, and remover, all in a single portable device. Designed to be easy to operate and use."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "labeler0"
item_state = "flight"
var/label = null
var/labels_left = 30
- var/mode = 0 //off or on.
+ var/mode = 0
/obj/item/hand_labeler/afterattack(atom/A, mob/user, proximity)
if(!proximity)
@@ -29,7 +30,9 @@
user.visible_message("[user] labels [A] as [label].", \
"You label [A] as [label].")
investigate_log("[key_name(user)] labelled [A] as [label].", INVESTIGATE_LABEL) // Investigate goes BEFORE rename so the original name is preserved in the log
- A.name = "[A.name] ([label])"
+ A.AddComponent(/datum/component/label, label)
+ playsound(A, 'sound/items/handling/component_pickup.ogg', 20, TRUE)
+ labels_left--
/obj/item/hand_labeler/attack_self(mob/user as mob)
mode = !mode
@@ -45,3 +48,20 @@
to_chat(user, "You set the text to '[str]'.")
else
to_chat(user, "You turn off \the [src].")
+
+/obj/item/hand_labeler/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/hand_labeler_refill))
+ to_chat(user, "You insert [I] into [src].")
+ user.drop_item()
+ qdel(I)
+ labels_left = initial(labels_left) //Yes, it's capped at its initial value
+ else
+ return ..()
+
+/obj/item/hand_labeler_refill
+ name = "hand labeler paper roll"
+ icon = 'icons/obj/bureaucracy.dmi'
+ desc = "A roll of paper. Use it on a hand labeler to refill it."
+ icon_state = "labeler_refill"
+ item_state = "electropack"
+ w_class = WEIGHT_CLASS_TINY
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 34acdcf0983..d80b175e757 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -87,6 +87,7 @@
popup.set_content(data)
if(!stars)
popup.add_script("marked.js", 'html/browser/marked.js')
+ popup.add_script("marked-paradise.js", 'html/browser/marked-paradise.js')
popup.add_head_content("[name]")
popup.open()
return data
@@ -562,10 +563,6 @@
name = "paper- 'Holodeck Disclaimer'"
info = "Brusies sustained in the holodeck can be healed simply by sleeping."
-/obj/item/paper/spells
- name = "paper- 'List of Available Spells (READ)'"
- info = "
LIST OF SPELLS AVAILABLE
Magic Missile: This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.
Fireball: This spell fires a fireball at a target and does not require wizard garb. Be careful not to fire it at people that are standing next to you.
Disintegrate:This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown.
Disable Technology: This spell disables all weapons, cameras and most other technology in range.
Smoke: This spell spawns a cloud of choking smoke at your location and does not require wizard garb.
Blind: This spell temporarly blinds a single person and does not require wizard garb.
Forcewall: This spell creates an unbreakable wall that lasts for 30 seconds and does not require wizard garb.
Blink: This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.
Teleport: This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.
Mutate: This spell causes you to turn into a hulk, and gain telekinesis for a short while.
Ethereal Jaunt: This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.
Knock: This spell opens nearby doors and does not require wizard garb.
"
-
/obj/item/paper/syndimemo
name = "paper- 'Memo'"
info = "GET DAT FUKKEN DISK"
@@ -589,17 +586,17 @@
/obj/item/paper/crumpled
name = "paper scrap"
icon_state = "scrap"
-
+
/obj/item/paper/syndicate
name = "paper"
header = "
"
info = ""
-
+
/obj/item/paper/nanotrasen
name = "paper"
header = "
"
info = ""
-
+
/obj/item/paper/central_command
name = "paper"
header ="
Nanotrasen Central Command
Official Expedited Memorandum
"
@@ -697,11 +694,17 @@
H.makeCluwne()
else if(myeffect == "Demote")
GLOB.event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order")
+ for(var/datum/data/record/R in sortRecord(GLOB.data_core.security))
+ if(R.fields["name"] == target.real_name)
+ R.fields["criminal"] = SEC_RECORD_STATUS_DEMOTE
+ R.fields["comments"] += "Central Command Demotion Order, given on [GLOB.current_date_string] [station_time_timestamp()] Process this demotion immediately. Failure to comply with these orders is grounds for termination."
+ update_all_mob_security_hud()
else if(myeffect == "Demote with Bot")
GLOB.event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order")
for(var/datum/data/record/R in sortRecord(GLOB.data_core.security))
if(R.fields["name"] == target.real_name)
- R.fields["criminal"] = "*Arrest*"
+ R.fields["criminal"] = SEC_RECORD_STATUS_ARREST
+ R.fields["comments"] += "Central Command Demotion Order, given on [GLOB.current_date_string] [station_time_timestamp()] Process this demotion immediately. Failure to comply with these orders is grounds for termination."
update_all_mob_security_hud()
if(fax)
var/turf/T = get_turf(fax)
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index d76765b61a7..a3ca2c5d410 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -11,7 +11,7 @@
var/amount = 30 //How much paper is in the bin.
var/list/papers = list() //List of papers put in the bin for reference.
var/letterhead_type
-
+
/obj/item/paper_bin/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
if(amount)
amount = 0
@@ -84,6 +84,7 @@
P.loc = user.loc
user.put_in_hands(P)
+ P.add_fingerprint(user)
to_chat(user, "You take [P] out of the [src].")
else
to_chat(user, "[src] is empty!")
@@ -143,7 +144,7 @@
add_fingerprint(user)
return
-
+
/obj/item/paper_bin/nanotrasen
name = "nanotrasen paper bin"
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index 7fac0e3386a..aa2a033f130 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -72,7 +72,7 @@
update_icon()
else if(is_hot(P))
- if(user.disabilities & CLUMSY && prob(10))
+ if((CLUMSY in user.mutations) && prob(10))
user.visible_message("[user] accidentally ignites [user.p_them()]self!", \
"You miss [src] and accidentally light yourself on fire!")
user.unEquip(P)
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 5ca53396253..d5cbbdc0ad6 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -340,7 +340,7 @@
return 0
else
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
- atom_say("Attention: Posterior Placed on Printing Plaque!")
+ atom_say("Attention: Posterior Placed on Printing Plaque!")
return 1
/obj/machinery/photocopier/emag_act(user as mob)
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 30e8cbd9541..45195bb1730 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -231,13 +231,13 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
var/atoms[] = list()
for(var/turf/the_turf in turfs)
// Add ourselves to the list of stuff to draw
- atoms.Add(the_turf);
+ atoms.Add(the_turf)
// As well as anything that isn't invisible.
for(var/atom/A in the_turf)
if(A.invisibility)
if(see_ghosts && istype(A,/mob/dead/observer))
var/mob/dead/observer/O = A
- if(O.following)
+ if(O.orbiting)
continue
if(user.mind && !(user.mind.assigned_role == "Chaplain"))
atoms.Add(image('icons/mob/mob.dmi', O.loc, pick(GLOB.SpookyGhosts), 4, SOUTH))
@@ -265,7 +265,7 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
var/atom/A = sorted[i]
if(A)
var/icon/img = getFlatIcon(A)//build_composite_icon(A)
- if(istype(A, /obj/item/areaeditor/blueprints))
+ if(istype(A, /obj/item/areaeditor/blueprints/ce))
blueprints = 1
// If what we got back is actually a picture, draw it.
@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
if(M.invisibility)
if(see_ghosts && istype(M,/mob/dead/observer))
var/mob/dead/observer/O = M
- if(O.following)
+ if(O.orbiting)
continue
if(!mob_detail)
mob_detail = "You can see a g-g-g-g-ghooooost! "
@@ -324,24 +324,26 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]."
return mob_detail
-/obj/item/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag)
- if(!on || !pictures_left || ismob(target.loc)) return
+/obj/item/camera/afterattack(atom/target, mob/user, flag)
+ if(!on || !pictures_left || ismob(target.loc))
+ return
captureimage(target, user, flag)
playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3)
-
+ set_light(3, 2, LIGHT_COLOR_TUNGSTEN)
+ addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2)
pictures_left--
desc = "A polaroid camera. It has [pictures_left] photos left."
to_chat(user, "[pictures_left] photos left.")
icon_state = icon_off
- on = 0
+ on = FALSE
if(istype(src,/obj/item/camera/spooky))
if(user.mind && user.mind.assigned_role == "Chaplain" && see_ghosts)
if(prob(24))
handle_haunt(user)
spawn(64)
icon_state = icon_on
- on = 1
+ on = TRUE
/obj/item/camera/proc/can_capture_turf(turf/T, mob/user)
var/viewer = user
@@ -560,13 +562,13 @@ GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","hor
talk_into(M, msg)
for(var/obj/machinery/computer/security/telescreen/T in GLOB.machines)
if(T.watchers[M] == camera)
- T.audible_message("(Newscaster) [M] says, '[msg]'", hearing_distance = 2)
+ T.atom_say(msg)
/obj/item/videocam/hear_message(mob/M as mob, msg)
if(camera && on)
for(var/obj/machinery/computer/security/telescreen/T in GLOB.machines)
if(T.watchers[M] == camera)
- T.audible_message("(Newscaster) [M] [msg]", hearing_distance = 2)
+ T.atom_say(msg)
///hauntings, like hallucinations but more spooky
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
new file mode 100644
index 00000000000..2234e2911a6
--- /dev/null
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -0,0 +1,215 @@
+//Bureaucracy machine!
+//Simply set this up in the hopline and you can serve people based on ticket numbers
+
+/obj/machinery/ticket_machine
+ name = "ticket machine"
+ icon = 'icons/obj/bureaucracy.dmi'
+ icon_state = "ticketmachine"
+ desc = "A marvel of bureaucratic engineering encased in an efficient plastic shell. It can be refilled with a hand labeler refill roll and linked to buttons with a multitool."
+ density = FALSE
+ maptext_height = 26
+ maptext_width = 32
+ maptext_x = 7
+ maptext_y = 10
+ layer = HIGH_OBJ_LAYER
+ var/ticket_number = 0 //Increment the ticket number whenever the HOP presses his button
+ var/current_number = 0 //What ticket number are we currently serving?
+ var/max_number = 100 //At this point, you need to refill it.
+ var/cooldown = 50
+ var/ready = TRUE
+ var/list/ticket_holders = list()
+ var/list/tickets = list()
+ var/id = 1
+
+/obj/machinery/ticket_machine/Destroy()
+ for(var/obj/item/ticket_machine_ticket/ticket in tickets)
+ ticket.visible_message("\the [ticket] disperses!")
+ qdel(ticket)
+ tickets.Cut()
+ return ..()
+
+/obj/machinery/ticket_machine/emag_act(mob/user) //Emag the ticket machine to dispense burning tickets, as well as randomize its number to destroy the HoP's mind.
+ if(emagged)
+ return
+ to_chat(user, "You overload [src]'s bureaucratic logic circuitry to its MAXIMUM setting.")
+ ticket_number = rand(0, max_number)
+ current_number = ticket_number
+ emagged = TRUE
+ for(var/obj/item/ticket_machine_ticket/ticket in tickets)
+ ticket.visible_message("\the [ticket] disperses!")
+ qdel(ticket)
+ tickets.Cut()
+ update_icon()
+
+/obj/machinery/ticket_machine/Initialize(mapload)
+ . = ..()
+ update_icon()
+
+/obj/machinery/ticket_machine/proc/increment()
+ if(current_number > ticket_number)
+ return
+ if(current_number && !(emagged) && tickets[current_number])
+ var/obj/item/ticket_machine_ticket/ticket = tickets[current_number]
+ ticket.audible_message("\the [tickets[current_number]] disperses!")
+ qdel(ticket)
+ if(current_number < ticket_number)
+ current_number ++ //Increment the one we're serving.
+ playsound(src, 'sound/misc/announce_dig.ogg', 50, FALSE)
+ atom_say("Now serving ticket #[current_number]!")
+ if(!(emagged) && tickets[current_number])
+ var/obj/item/ticket_machine_ticket/ticket = tickets[current_number]
+ ticket.audible_message("\the [tickets[current_number]] vibrates!")
+ update_icon() //Update our icon here rather than when they take a ticket to show the current ticket number being served
+
+/obj/machinery/door_control/ticket_machine_button
+ name = "increment ticket counter"
+ desc = "Use this button after you've served someone to tell the next person to come forward."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "doorctrl0"
+ req_access = list()
+ id = 1
+ var/cooldown = FALSE
+
+
+/obj/machinery/door_control/ticket_machine_button/attack_hand(mob/user)
+ if(allowed(usr) || user.can_advanced_admin_interact())
+ icon_state = "doorctrl1"
+ addtimer(CALLBACK(src, /obj/machinery/door_control/ticket_machine_button/.proc/update_icon), 15)
+ for(var/obj/machinery/ticket_machine/M in GLOB.machines)
+ if(M.id == id)
+ if(cooldown)
+ return
+ cooldown = TRUE
+ M.increment()
+ addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
+ else
+ to_chat(usr, "Access denied.")
+ flick("doorctrl-denied", src)
+
+/obj/machinery/door_control/ticket_machine_button/update_icon()
+ if(!(stat & NOPOWER))
+ icon_state = "doorctrl0"
+
+/obj/machinery/ticket_machine/update_icon()
+ switch(ticket_number) //Gives you an idea of how many tickets are left
+ if(0 to 49)
+ icon_state = "ticketmachine_100"
+ if(50 to 99)
+ icon_state = "ticketmachine_50"
+ if(100)
+ icon_state = "ticketmachine_0"
+ handle_maptext()
+
+/obj/machinery/ticket_machine/proc/handle_maptext()
+ switch(ticket_number) //This is here to handle maptext offsets so that the numbers align.
+ if(0 to 9)
+ maptext_x = 13
+ if(10 to 99)
+ maptext_x = 10
+ if(100)
+ maptext_x = 8
+ maptext = "[ticket_number]"
+
+/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/hand_labeler_refill))
+ if(!(ticket_number >= max_number))
+ to_chat(user, "[src] refuses [I]! There [max_number-ticket_number==1 ? "is" : "are"] still [max_number-ticket_number] ticket\s left!")
+ return
+ to_chat(user, "You start to refill [src]'s ticket holder (doing this will reset its ticket count!).")
+ if(do_after(user, 30, target = src))
+ to_chat(user, "You insert [I] into [src] as it whirs nondescriptly.")
+ user.drop_item()
+ qdel(I)
+ ticket_number = 0
+ current_number = 0
+ for(var/obj/item/ticket_machine_ticket/ticket in tickets)
+ ticket.audible_message("\the [ticket] disperses!")
+ qdel(ticket)
+ tickets.Cut()
+ max_number = initial(max_number)
+ update_icon()
+ return
+ else
+ return ..()
+
+/obj/machinery/ticket_machine/proc/reset_cooldown()
+ ready = TRUE
+
+/obj/machinery/ticket_machine/attack_hand(mob/living/carbon/user)
+ . = ..()
+ if(!ready)
+ to_chat(user,"You press the button, but nothing happens...")
+ return
+ if(ticket_number >= max_number)
+ to_chat(user,"Ticket supply depleted, please refill this unit with a hand labeller refill cartridge!")
+ return
+ if((user.UID() in ticket_holders) && !(emagged))
+ to_chat(user, "You already have a ticket!")
+ return
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE)
+ ticket_number ++
+ to_chat(user, "You take a ticket from [src], looks like you're ticket number #[ticket_number]...")
+ var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src))
+ theirticket.name = "Ticket #[ticket_number]"
+ theirticket.maptext = "[ticket_number]"
+ theirticket.saved_maptext = "[ticket_number]"
+ theirticket.ticket_number = ticket_number
+ theirticket.source = src
+ theirticket.owner = user.UID()
+ user.put_in_hands(theirticket)
+ ticket_holders += user.UID()
+ tickets += theirticket
+ if(emagged) //Emag the machine to destroy the HOP's life.
+ ready = FALSE
+ addtimer(CALLBACK(src, .proc/reset_cooldown), cooldown)//Small cooldown to prevent piles of flaming tickets
+ theirticket.fire_act()
+ user.drop_item()
+ user.adjust_fire_stacks(1)
+ user.IgniteMob()
+
+// Stop AI penetrating the bureaucracy
+/obj/machinery/ticket_machine/attack_ai(mob/user)
+ return
+
+/obj/item/ticket_machine_ticket
+ name = "Ticket"
+ desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
+ icon = 'icons/obj/bureaucracy.dmi'
+ icon_state = "ticket"
+ maptext_x = 7
+ maptext_y = 10
+ w_class = WEIGHT_CLASS_TINY
+ resistance_flags = FLAMMABLE
+ max_integrity = 50
+ var/saved_maptext = null
+ var/owner //soft ref of the ticket owner's UID()
+ var/obj/machinery/ticket_machine/source
+ var/ticket_number
+
+/obj/item/ticket_machine_ticket/attack_hand(mob/user)
+ . = ..()
+ maptext = saved_maptext //For some reason, storage code removes all maptext off objs, this stops its number from being wiped off when taken out of storage.
+
+/obj/item/ticket_machine_ticket/attackby(obj/item/P, mob/living/carbon/human/user, params) //Stolen from papercode
+ ..()
+ if(is_hot(P))
+ if((CLUMSY in user.mutations) && prob(10))
+ user.visible_message("[user] accidentally ignites [user.p_them()]self!", \
+ "You miss the paper and accidentally light yourself on fire!")
+ user.drop_item()
+ user.adjust_fire_stacks(1)
+ user.IgniteMob()
+ return
+ user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!")
+ fire_act()
+
+/obj/item/paper/extinguish()
+ ..()
+ update_icon()
+
+/obj/item/ticket_machine_ticket/Destroy()
+ if(owner && source)
+ source.ticket_holders -= owner
+ source.tickets[ticket_number] = null
+ source = null
+ return ..()
diff --git a/code/modules/pda/app.dm b/code/modules/pda/app.dm
index 189f354446f..655bb891de5 100644
--- a/code/modules/pda/app.dm
+++ b/code/modules/pda/app.dm
@@ -50,8 +50,6 @@
if(!pda.notifying_programs.len)
pda.overlays -= image('icons/obj/pda.dmi', "pda-r")
-/datum/data/pda/proc/
-
// An app has a button on the home screen and its own UI
/datum/data/pda/app
name = "App"
diff --git a/code/modules/pda/cart_apps.dm b/code/modules/pda/cart_apps.dm
index 6c03241a096..d47f4184daf 100644
--- a/code/modules/pda/cart_apps.dm
+++ b/code/modules/pda/cart_apps.dm
@@ -366,6 +366,7 @@
JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y)
else
JaniData["user_loc"] = list("x" = 0, "y" = 0)
+
var/MopData[0]
for(var/obj/item/mop/M in GLOB.janitorial_equipment)
var/turf/ml = get_turf(M)
@@ -375,10 +376,6 @@
var/direction = get_dir(pda, M)
MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry")
- if(!MopData.len)
- MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
-
-
var/BucketData[0]
for(var/obj/structure/mopbucket/B in GLOB.janitorial_equipment)
var/turf/bl = get_turf(B)
@@ -386,13 +383,10 @@
if(bl.z != cl.z)
continue
var/direction = get_dir(pda,B)
- BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
-
- if(!BucketData.len)
- BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
+ BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "volume" = B.reagents.total_volume, "max_volume" = B.reagents.maximum_volume)
var/CbotData[0]
- for(var/mob/living/simple_animal/bot/cleanbot/B in GLOB.simple_animals)
+ for(var/mob/living/simple_animal/bot/cleanbot/B in GLOB.bots_list)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
@@ -400,9 +394,6 @@
var/direction = get_dir(pda,B)
CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline")
-
- if(!CbotData.len)
- CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CartData[0]
for(var/obj/structure/janitorialcart/B in GLOB.janitorial_equipment)
var/turf/bl = get_turf(B)
@@ -410,12 +401,10 @@
if(bl.z != cl.z)
continue
var/direction = get_dir(pda,B)
- CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
- if(!CartData.len)
- CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
+ CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "volume" = B.reagents.total_volume, "max_volume" = B.reagents.maximum_volume)
- JaniData["mops"] = MopData
- JaniData["buckets"] = BucketData
- JaniData["cleanbots"] = CbotData
- JaniData["carts"] = CartData
+ JaniData["mops"] = MopData.len ? MopData : null
+ JaniData["buckets"] = BucketData.len ? BucketData : null
+ JaniData["cleanbots"] = CbotData.len ? CbotData : null
+ JaniData["carts"] = CartData.len ? CartData : null
data["janitor"] = JaniData
diff --git a/code/modules/pda/messenger.dm b/code/modules/pda/messenger.dm
index 066db440cc8..5ccef4dee41 100644
--- a/code/modules/pda/messenger.dm
+++ b/code/modules/pda/messenger.dm
@@ -151,24 +151,33 @@
useMS = MS
break
- var/datum/signal/signal = pda.telecomms_process()
+ var/turf/sender_pos = get_turf(U)
+ var/turf/recipient_pos = get_turf(P)
- var/useTC = 0
- if(signal)
- if(signal.data["done"])
- useTC = 1
- var/turf/pos = get_turf(P)
- // TODO: Make the radio system cooperate with the space manager
- if(pos.z in signal.data["level"])
- useTC = 2
- //Let's make this barely readable
- if(signal.data["compression"] > 0)
- t = Gibberish(t, signal.data["compression"] + 50)
+ // Can the message be sent
+ var/sendable = FALSE
+ // Can the message be received?
+ var/receivable = FALSE
+
+ for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
+ if(C.zlevel_reachable(sender_pos.z))
+ sendable = TRUE
+ if(C.zlevel_reachable(recipient_pos.z))
+ receivable = TRUE
+ // Once both are done, exit the loop
+ if(sendable && receivable)
+ break
+
+ if(!sendable) // Are we in the range of a reciever?
+ to_chat(U, "ERROR: No connection to server.")
+ return
+
+ if(!receivable) // Is our recipient in the range of a reciever?
+ to_chat(U, "ERROR: No connection to recipient.")
+ return
+
+ if(useMS && sendable && receivable) // only send the message if its going to work
- if(useMS && useTC) // only send the message if it's stable
- if(useTC != 2) // Does our recipient have a broadcaster on their level?
- to_chat(U, "ERROR: Cannot reach recipient.")
- return
useMS.send_pda_message("[P.owner]","[pda.owner]","[t]")
tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]")))
diff --git a/code/modules/pda/mob_hunt_game_app.dm b/code/modules/pda/mob_hunt_game_app.dm
index c48ebdd4e9e..c72aa6d0d41 100644
--- a/code/modules/pda/mob_hunt_game_app.dm
+++ b/code/modules/pda/mob_hunt_game_app.dm
@@ -47,7 +47,7 @@
SSmob_hunt.connected_clients += src
connected = 1
if(pda)
- pda.audible_message("[bicon(pda)] Connection established. Capture all of the mobs, [pda.owner ? pda.owner : "hunter"]!", null, 2)
+ pda.atom_say("Connection established. Capture all of the mobs, [pda.owner ? pda.owner : "hunter"]!")
return 1
/datum/data/pda/app/mob_hunter_game/proc/get_player()
@@ -67,7 +67,7 @@
connected = 0
//show a disconnect message if we were disconnected involuntarily (reason argument provided)
if(pda && reason)
- pda.audible_message("[bicon(pda)] Disconnected from server. Reason: [reason].", null, 2)
+ pda.atom_say("Disconnected from server. Reason: [reason].")
/datum/data/pda/app/mob_hunter_game/program_process()
if(!SSmob_hunt || !connected)
diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm
index 0e5c58f968a..f6f02e3457f 100644
--- a/code/modules/pda/pdas.dm
+++ b/code/modules/pda/pdas.dm
@@ -38,11 +38,8 @@
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
ttone = "honk"
- trip_stun = 8
- trip_weaken = 5
- trip_chance = 100
- trip_walksafe = TRUE
- trip_verb = TV_SLIP
+/obj/item/pda/clown/ComponentInitialize()
+ AddComponent(/datum/component/slippery, src, 8, 5, 100)
/obj/item/pda/mime
default_cartridge = /obj/item/cartridge/mime
@@ -191,7 +188,7 @@
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
if(M)
M.m_hidden = 1
-
+
//Some spare PDAs in a box
/obj/item/storage/box/PDAs
name = "spare PDAs"
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index ca2f1e13ff7..409abe3d724 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1,8 +1,3 @@
-#define APC_WIRE_IDSCAN 1
-#define APC_WIRE_MAIN_POWER1 2
-#define APC_WIRE_MAIN_POWER2 3
-#define APC_WIRE_AI_CONTROL 4
-
//update_state
#define UPSTATE_CELL_IN 1
#define UPSTATE_OPENED1 2
@@ -75,7 +70,6 @@
var/locked = 1
var/coverlocked = 1
var/aidisabled = 0
- var/tdir = null
var/obj/machinery/power/terminal/terminal = null
var/lastused_light = 0
var/lastused_equip = 0
@@ -152,7 +146,7 @@
if(terminal)
terminal.connect_to_network()
-/obj/machinery/power/apc/New(turf/loc, ndir, building = 0)
+/obj/machinery/power/apc/New(turf/loc, direction, building = 0)
if(!armor)
armor = list("melee" = 20, "bullet" = 20, "laser" = 10, "energy" = 100, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50)
..()
@@ -160,16 +154,12 @@
GLOB.apcs = sortAtom(GLOB.apcs)
wires = new(src)
- // offset 24 pixels in direction of dir
- // this allows the APC to be embedded in a wall, yet still inside an area
- if(building)
- setDir(ndir)
- tdir = dir // to fix Vars bug
- setDir(SOUTH)
- pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
- pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
if(building)
+ // Offset 24 pixels in direction of dir. This allows the APC to be embedded in a wall, yet still inside an area
+ setDir(direction) // This is only used for pixel offsets, and later terminal placement. APC dir doesn't affect its sprite since it only has one orientation.
+ set_pixel_offsets_from_dir(24, -24, 24, -24)
+
area = get_area(src)
area.apc |= src
opened = 1
@@ -182,7 +172,7 @@
/obj/machinery/power/apc/Destroy()
GLOB.apcs -= src
if(malfai && operating)
- malfai.malf_picker.processing_time = Clamp(malfai.malf_picker.processing_time - 10,0,1000)
+ malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000)
area.power_light = 0
area.power_equip = 0
area.power_environ = 0
@@ -199,8 +189,8 @@
/obj/machinery/power/apc/proc/make_terminal()
// create a terminal object at the same position as original turf loc
// wires will attach to this
- terminal = new/obj/machinery/power/terminal(src.loc)
- terminal.setDir(tdir)
+ terminal = new/obj/machinery/power/terminal(get_turf(src))
+ terminal.setDir(dir)
terminal.master = src
/obj/machinery/power/apc/Initialize(mapload)
@@ -249,7 +239,7 @@
else if(has_electronics && !terminal)
. += "Electronics installed but not wired."
else /* if(!has_electronics && !terminal) */
- . += "There is no electronics nor connected wires."
+ . += "There are no electronics nor connected wires."
else
if(stat & MAINT)
. += "The cover is closed. Something wrong with it: it doesn't work."
@@ -430,11 +420,11 @@
if(stat & (NOPOWER | BROKEN))
return
if(!second_pass) //The first time, we just cut overlays
- addtimer(CALLBACK(src, .get_spooked, TRUE), 1)
+ addtimer(CALLBACK(src, /obj/machinery/power/apc/proc.get_spooked, TRUE), 1)
cut_overlays()
else
flick("apcemag", src) //Second time we cause the APC to update its icon, then add a timer to update icon later
- addtimer(CALLBACK(src, .proc/update_icon, TRUE), 10)
+ addtimer(CALLBACK(src, /obj/machinery/power/apc/proc.update_icon, TRUE), 10)
//attack with an item - open/close cover, insert cell, or (un)lock interface
/obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params)
@@ -550,7 +540,7 @@
/obj/machinery/power/apc/crowbar_act(mob/living/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(opened) // a) on open apc
if(has_electronics==1)
@@ -1062,7 +1052,8 @@
occupier.eyeobj.name = "[occupier.name] (AI Eye)"
if(malf.parent)
qdel(malf)
- occupier.verbs += /mob/living/silicon/ai/proc/corereturn
+ var/datum/action/innate/ai/return_to_core/R = new
+ R.Grant(occupier)
occupier.cancel_camera()
if((seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) && malf.nuking)
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
@@ -1338,7 +1329,7 @@
/obj/machinery/power/apc/proc/set_broken()
if(malfai && operating)
- malfai.malf_picker.processing_time = Clamp(malfai.malf_picker.processing_time - 10,0,1000)
+ malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000)
stat |= BROKEN
operating = 0
if(occupier)
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 7260c836d78..b6c65d979cf 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -79,8 +79,10 @@ By design, d1 is the smallest direction and d2 is the highest
return ..() // then go ahead and delete the cable
/obj/structure/cable/deconstruct(disassembled = TRUE)
+ var/turf/T = get_turf(src)
+ if(usr)
+ investigate_log("was deconstructed by [key_name(usr, 1)] in [get_area(usr)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires")
if(!(flags & NODECONSTRUCT))
- var/turf/T = get_turf(src)
if(d1) // 0-X cables are 1 unit, X-X cables are 2 units long
new/obj/item/stack/cable_coil(T, 2, paramcolor = color)
else
@@ -123,7 +125,7 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/proc/surplus()
if(powernet)
- return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
+ return clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
@@ -139,7 +141,7 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/proc/delayed_surplus()
if(powernet)
- return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
+ return clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 24f55d34454..b92b456890f 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -160,7 +160,7 @@
/obj/item/stock_parts/cell/proc/get_electrocute_damage()
if(charge >= 1000)
- return Clamp(20 + round(charge / 25000), 20, 195) + rand(-5, 5)
+ return clamp(20 + round(charge / 25000), 20, 195) + rand(-5, 5)
else
return 0
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 78c2561ae7d..3e8d71b3280 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -39,81 +39,86 @@
if(3)
. += "The casing is closed."
-/obj/machinery/light_construct/attackby(obj/item/W as obj, mob/living/user as mob, params)
- src.add_fingerprint(user)
- if(istype(W, /obj/item/wrench))
- if(src.stage == 1)
- playsound(src.loc, W.usesound, 75, 1)
- to_chat(usr, "You begin deconstructing [src].")
- if(!do_after(usr, 30 * W.toolspeed, target = src))
+/obj/machinery/light_construct/wrench_act(mob/living/user, obj/item/I)
+ . = TRUE
+ switch(stage)
+ if(1)
+ to_chat(user, "You begin deconstructing [src].")
+ if(!I.use_tool(src, user, 30, volume = I.tool_volume))
return
- new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
- user.visible_message("[user.name] deconstructs [src].", \
- "You deconstruct [src].", "You hear a noise.")
- playsound(src.loc, W.usesound, 75, 1)
+ new /obj/item/stack/sheet/metal(get_turf(loc), sheets_refunded)
+ user.visible_message("[user] deconstructs [src].", \
+ "You deconstruct [src].", "You hear a noise.")
qdel(src)
- if(src.stage == 2)
- to_chat(usr, "You have to remove the wires first.")
- return
+ if(2)
+ to_chat(user, "You have to remove the wires first.")
+ if(3)
+ to_chat(user, "You have to unscrew the case first.")
- if(src.stage == 3)
- to_chat(usr, "You have to unscrew the case first.")
- return
-
- if(istype(W, /obj/item/wirecutters))
- if(src.stage != 2) return
- src.stage = 1
- switch(fixture_type)
- if("tube")
- src.icon_state = "tube-construct-stage1"
- if("bulb")
- src.icon_state = "bulb-construct-stage1"
- new /obj/item/stack/cable_coil(get_turf(src.loc), 1, paramcolor = COLOR_RED)
- user.visible_message("[user.name] removes the wiring from [src].", \
- "You remove the wiring from [src].", "You hear a noise.")
- playsound(loc, W.usesound, 100, 1)
+/obj/machinery/light_construct/wirecutter_act(mob/living/user, obj/item/I)
+ if(stage != 2)
return
+ . = TRUE
+ if(!I.use_tool(src, user, 0))
+ return
+ playsound(loc, I.usesound, 100, 1)
+ . = TRUE
+ stage = 1
+ switch(fixture_type)
+ if("tube")
+ icon_state = "tube-construct-stage1"
+ if("bulb")
+ icon_state = "bulb-construct-stage1"
+ new /obj/item/stack/cable_coil(get_turf(loc), 1, paramcolor = COLOR_RED)
+ user.visible_message("[user] removes the wiring from [src].", \
+ "You remove the wiring from [src].", "You hear a noise.")
+
+/obj/machinery/light_construct/screwdriver_act(mob/living/user, obj/item/I)
+ if(stage != 2)
+ return
+ . = TRUE
+ if(!I.use_tool(src, user, 0))
+ return
+ switch(fixture_type)
+ if("tube")
+ icon_state = "tube-empty"
+ if("bulb")
+ icon_state = "bulb-empty"
+ stage = 3
+ user.visible_message("[user] closes [src]'s casing.", \
+ "You close [src]'s casing.", "You hear a noise.")
+ playsound(loc, I.usesound, 75, 1)
+
+ switch(fixture_type)
+ if("tube")
+ newlight = new /obj/machinery/light/built(loc)
+ if("bulb")
+ newlight = new /obj/machinery/light/small/built(loc)
+
+ newlight.setDir(dir)
+ transfer_fingerprints_to(newlight)
+ qdel(src)
+
+/obj/machinery/light_construct/attackby(obj/item/W, mob/living/user, params)
+ add_fingerprint(user)
if(istype(W, /obj/item/stack/cable_coil))
- if(src.stage != 1) return
+ if(stage != 1)
+ return
var/obj/item/stack/cable_coil/coil = W
coil.use(1)
switch(fixture_type)
if("tube")
- src.icon_state = "tube-construct-stage2"
+ icon_state = "tube-construct-stage2"
if("bulb")
- src.icon_state = "bulb-construct-stage2"
- src.stage = 2
+ icon_state = "bulb-construct-stage2"
+ stage = 2
playsound(loc, coil.usesound, 50, 1)
- user.visible_message("[user.name] adds wires to [src].", \
- "You add wires to [src].")
+ user.visible_message("[user.name] adds wires to [src].", \
+ "You add wires to [src].")
return
- if(istype(W, /obj/item/screwdriver))
- if(src.stage == 2)
- switch(fixture_type)
- if("tube")
- src.icon_state = "tube-empty"
- if("bulb")
- src.icon_state = "bulb-empty"
- src.stage = 3
- user.visible_message("[user.name] closes [src]'s casing.", \
- "You close [src]'s casing.", "You hear a noise.")
- playsound(src.loc, W.usesound, 75, 1)
-
- switch(fixture_type)
-
- if("tube")
- newlight = new /obj/machinery/light/built(src.loc)
- if("bulb")
- newlight = new /obj/machinery/light/small/built(src.loc)
-
- newlight.dir = src.dir
- src.transfer_fingerprints_to(newlight)
- qdel(src)
- return
- else
- return ..()
+ return ..()
/obj/machinery/light_construct/blob_act(obj/structure/blob/B)
if(B && B.loc == loc)
@@ -629,6 +634,12 @@
shatter()
return ..()
+/obj/item/light/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["glass"] += 1
+ C.stored_comms["metal"] += 1
+ qdel(src)
+ return TRUE
+
/obj/item/light/tube
name = "light tube"
desc = "A replacement light tube."
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index c74f9cc0007..ff4074d045e 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -42,7 +42,7 @@
/obj/machinery/power/proc/surplus()
if(powernet)
- return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
+ return clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
@@ -58,7 +58,7 @@
/obj/machinery/power/proc/delayed_surplus()
if(powernet)
- return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
+ return clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
@@ -375,6 +375,7 @@
return null
/area/proc/get_apc()
- for(var/obj/machinery/power/apc/APC in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/APC = thing
if(APC.area == src)
return APC
diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm
index a4ab64a2099..f73498cff2c 100644
--- a/code/modules/power/powernet.dm
+++ b/code/modules/power/powernet.dm
@@ -97,6 +97,6 @@
/datum/powernet/proc/get_electrocute_damage()
if(avail >= 1000)
- return Clamp(20 + round(avail / 25000), 20, 195) + rand(-5, 5)
+ return clamp(20 + round(avail / 25000), 20, 195) + rand(-5, 5)
else
return 0
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 9579fcc6bf4..ceb3b578588 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -21,11 +21,8 @@
var/state = 0
var/locked = 0
- var/frequency = 0
- var/id_tag = null
var/projectile_type = /obj/item/projectile/beam/emitter
var/projectile_sound = 'sound/weapons/emitter.ogg'
- var/datum/radio_frequency/radio_connection
var/datum/effect_system/spark_spread/sparks
/obj/machinery/power/emitter/Initialize(mapload)
@@ -40,8 +37,6 @@
sparks = new
sparks.attach(src)
sparks.set_up(5, 1, src)
- if(frequency)
- set_frequency(frequency)
/obj/machinery/power/emitter/RefreshParts()
var/max_firedelay = 120
@@ -59,14 +54,6 @@
power_usage -= 50 * M.rating
active_power_usage = power_usage
- //Radio remote control
-/obj/machinery/power/emitter/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
-
-
/obj/machinery/power/emitter/verb/rotate()
set name = "Rotate"
set category = "Object"
@@ -86,44 +73,7 @@
return
rotate()
-/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/multitool/P)
- return {"
-
- Current Project Maintainers:-Click Here-
- Currently Active GitHub contributor list:-Click Here-
- Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
- Spriters: FullOfSkittles
- Sounds:
- Main Testers: Anyone who has submitted a bug to the issue tracker
- Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image. Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
- Have a bug to report? Visit our Issue Tracker.
- Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred.
-
-
-
-
-
-
-
-
27 October 2019
-
AdamElTablawy updated:
-
-
Xenobiology can no longer produce hellhounds with gold slime cores.
-
-
AzuleUtama updated:
-
-
Vampire's shape shift ability and DNA scrambler item now clear flavour text on use.
-
-
Darkmight9 updated:
-
-
Adds a wide variety of craftable decorations! You can find them in the new 'Decorations' tab in the crafting menu.
-
tweaked the duct tape component so that you can now add it to items to make them naturally stick to walls.
-
added decorative sprites.
-
-
Fox McCloud updated:
-
-
windows are easier to break
-
Adds in the Rod of Asclepius, a healing item that carries an immense burden
-
Fixes Bubblegum spawning being ridiculously rare
-
Fixes planetary atmos not correctly happening
-
Fixes atmos pipe unwrenching
-
Survival pod medical vendors only have 2 pairs of splints instead of a wide array of medicines
-
Hivelord core, when used on someone, no longer fully revives them; instead it heals 25 burn, 25 brute, resets body temperature, removes all CC, cures all internal bleeding, and mends all fractures (slowdown bonus still stays
-
updates the close icon for storage to not be a trashy codersprite
-
Fixes excessive mob and tendril clumping on Lavaland
-
Fixes being able to exploit the destructive analyzer for unlimited materials
-
Fixes Hierophant arena atmos
-
-
Ionward updated:
-
-
fixed Battlemage armor having an unintended helmet light
-
added Vox versions of Battlemage, Paranormal, Inquisitor, Berserker, and Syndicate Elite Hardsuits.
-
-
SteelSlayer updated:
-
-
Fixes the RPED and bluespace RPED not displaying a list of parts in players chat when used on a machine
-
-
TDSSS updated:
-
-
yellow documents are no longer indestructible.
-
-
Tayyyyyyy updated:
-
-
single quotes showing up weird in names and announcement titles
-
-
Terilia updated:
-
-
Headcrab Nests
-
Headcrabs can now eat dead simple_animal corpses to regain 10 hp.
-
Poison Headcrabs will not inject LSD anymore.
-
Headcrabs have more HP and some do more damage.
-
Headcrabs will not stop attacking people after they are unconscious.
-
Headcrab Nest DMI
-
-
Ty-Omaha updated:
-
-
Admin attack log level of heirophant club updated
-
-
actioninja updated:
-
-
Nanoui interfaces in fancy mode now open more cleanly
-
-
craftxbox updated:
-
-
Vanilla JS Regex for chat highlighting
-
Removed jquery mark
-
quickfix to stop people using the scanner inside it
-
-
farie82 updated:
-
-
Cult whispering now uses your real name
-
Fixed the invisible blob zombies
-
A runtime in blob/factory/run_action
-
-
-
13 October 2019
-
Darkmight9 updated:
-
-
Re-added the handheld defib sprites
-
-
Fox McCloud updated:
-
-
Fixes wrench attacking telepads
-
performance improvements for xenobio stuff
-
LINDA is much more aggressive at distributing gas between turfs in an excited group
Reverted autoban using legacy system causing issues
-
-
streather updated:
-
-
fixed a typo in the autolathe
-
-
-
09 October 2019
-
Darkmight9 updated:
-
-
Gives the handheld defib a new sprite
-
-
Fox McCloud updated:
-
-
DNA vault requires 5 pico manipulators and 5 super capacitors instead of quadratic capacitors
-
Powers of the DNA vault adjusted
-
DNA vault no longer allows you to have unlimited genetics powers.
-
All previous powers removed with the exception of no breathing
-
New powers: breathable plasma immunity+virus immunity, heat immunity+burn reduction, speed increase, species armoring+pierce immunity, stun reduction, and action speed increase
-
Removes consoles screens; use plane old glass in place of them. Holy sheet, they were a pane.
-
Adds being able to make leather with the bio-generator
-
removed a lot of leather-related recipes from the bio-generator; these have been moved to leather crafting
-
can make hide mantles with leather
-
wearing pants while wearing an undershirt means your arms and chest are covered
-
Fixes AI swarmers not doing anything
-
swarmers can eat circuitboards and their own shells now
-
Fixed being able to eat soil
-
de-activated swarmer shells give 10,000 metal and 4,000 glass instead of 100 metal and 400 glass.
-
Fixes lavaland swarmers not being able to teleport people away
-
Swarmers can place lattice over lava
-
Floors no longer get dirty by walking on them
-
Zone selection tweaked; shouldn't notice anything different
-
melting research lockboxes no longer dumps the contents
-
Fixes reflective blobs using horrifying code that didn't reflect things *properly*
-
Fixes APCs not being hackable
-
Fixes explosions not properly interacting with storage items
-
-
Ionward updated:
-
-
Fixed a single pixel offset on Grey's Bags of Holding sprite.
-
-
JKnutson101 updated:
-
-
Shades can be stored in any Soul Stone.
-
Shades can once again be stored in Soul Stones.
-
Non-cultists and Non-wizards can no longer use most Soul Stones.
-
Cult Specters properly log as antags.
-
Cult Specters are properly removed from the cult on death.
-
-
KasparoVy updated:
-
-
Fixes an issue with the Tajaran striped tail's wagging animation by removing an extra frame.
-
-
PidgeyThePirate updated:
-
-
The abductor's silencer now actually silences radios for 10-20 seconds.
-
-
SteelSlayer and McRamon updated:
-
-
Added a new subtype of shade used exclusively by cultists to prevent chaplains metagaming with their shade sprites
-
Renamed path names for the altar and archives to be less confusing, and replaced all instances of the path names to reflect the change
-
Replaced nearly every sprite for reaper cult, including constructs, structures, airlocks and the reaper himself.
-
Removed the old reaper cult construct sprites
-
-
craftxbox updated:
-
-
cult teleport rune teleporting ai eye
-
-
-
07 October 2019
-
AffectedArc07 updated:
-
-
SQL now properly disconnects at end round
-
-
Couls updated:
-
-
reviver implant now heals even when you're conscious
-
-
Darkmight9 updated:
-
-
Hair styles, body markings, clothes, and other character customization options are now alphabetized.
-
-
Fox McCloud updated:
-
-
Most things are universally damageable
-
Acid melts things a bit differently now
-
Lava actually sets most things on fire.
-
Captain no longer has access to his display case by default
-
Xenos can break open vents
-
Fix syringe in-hand icon not updating
-
Fixes syringes not having materials
-
Lethal injection syringes should be a bit more...lethal
-
PDA health scans should be more in line with regular health analyzer scans
-
some blood type fixes, nothing noteworthy
-
-
Ionward updated:
-
-
fixed invisible Drask surgical masks
-
added Drask surgery cap icons
-
-
JKnutson101 updated:
-
-
Pylons heal robotic limbs.
-
Soul Shards fail when used on mobs that have never had a ckey.
-
Soul Stone Shards properly poll dead chat to be filled.
-
Incorrect icon path for reaper tome
-
-
Kyep updated:
-
-
Fixed the medkit spawning in the syndie depot being empty.
-
-
PidgeyThePirate updated:
-
-
Revived simple animals keep their ability to pull things and their density if they originally had it.
-
replaced the Lavaland winter dome ATV with a snowmobile.
-
The snowmobile key in the winterdome now accompanies an actual snowmobile instead of an incompatible vehicle.
-
-
SteelSlayer updated:
-
-
Added GPS coordinates under that status tab for cyborgs which have a GPS
-
You can no longer fire mining cyborg's KA with no cooldown
-
Bought items from the wizard spell book are first placed into any empty hands. If all hands are full, it places the item on the ground.
-
Cultists no longer get more than one summon objective
-
Mindslaves now show up in their own "Mindslaves" section in the check antagonists panel
-
Mindslaves will now get their objectives added to their notes and announced in their chat properly
-
Mindslaves will now have the red (A) in admin attack logs, which shows that the attacker is an antag
-
-
TDSSS updated:
-
-
fixed visual issues in beach gateway
-
-
farie82 updated:
-
-
Tickets can now be unassigned by staff members.
-
Toxic compensation now deals the right amount of toxic damage. Instead of just the last healed damage
-
-
-
30 September 2019
-
Couls updated:
-
-
Renames slime organs to be more player friendly
-
-
PidgeyThePirate updated:
-
-
The Ripley now collects all the ore it unearths after drilling.
-
-
SteelSlayer updated:
-
-
Cultists will no longer get multiple summoning objectives
-
-
TheSardele updated:
-
-
MULEbots no longer cause any damage when running over SSDs.
-
-
Ty-Omaha updated:
-
-
"Factual" changed to Actual in the explosion doppler array detector system
-
-
-
29 September 2019
-
AzuleUtama updated:
-
-
The camera bug now lists all cameras in alphabetical order.
-
-
Couls updated:
-
-
species without bones no longer have ribs or a skull either
-
slime heart and fleshy masses no longer go invisible after being removed through surgery or being eaten or necrotizing
-
-
Evankhell561 updated:
-
-
replace high power cells with high power cell+
-
-
Fox McCloud updated:
-
-
can insert keys into vehicles instead of having to hold them in your hand (alt-click while riding a vehicle to remove the key); lava boat still requires holding the key in your hand
-
Fixes moving diagonally with vehicles making you super fast
-
Vehicles now factor in the configured human movement delay; this means all vehicles are slower than they previously were
-
fixes a bug with mobs on vehicles causing incorrect space transitions
-
ATV sprites updated
-
Slime speed potions can now apply to vehicles, which makes them faster
-
-
JKnutson101 updated:
-
-
Allows for robotic hands, feet, and groin to undergo customization surgery.
-
-
PidgeyThePirate updated:
-
-
Abductor surgery will now remove heart subtypes.
-
Capitalized abductor surgery names for consistency with the surgery UI.
-
changelings no longer go bald after reviving.
-
-
-
27 September 2019
-
PidgeyThePirate updated:
-
-
Rebooting a drone no longer requires both engineering and robotics access.
-
fixed a rare glitch in which a guardian that is killed instantly (i.e by a wand of death) may draw its charge into null space.
-
bluespace anomalies no longer teleport ghosts when their event fires.
-
-
SteelSlayer updated:
-
-
Fixes round-start autotraitors not getting their objectives and uplink codes
-
-
-
26 September 2019
-
AzuleUtama updated:
-
-
Improvised shotguns are now in the correct tab when trying to craft them.
-
-
Couls updated:
-
-
Slime lungs and heart
-
Slimes no longer take toxins damage from blood loss
-
Slimes no longer take brute damage in crit
-
Slimes now breathe
-
slimes now use new crit
-
-
Kyep updated:
-
-
Fixed NPC redsuited syndicates from being unable to move in space.
-
Fixed NPC bots thinking that they can path through airlocks which are welded shut. refactor: Refactors some safety checks so that its impossible for depot mobs to generate runtimes in rare cases (e.g: admins spawning them outside the depot for testing)
-
-
MrMagolor updated:
-
-
Cult pylons no longer delete unsimulated walls and turn them into floors.
-
Cult pylons now turn simulated walls into cult walls.
-
-
TDSSS updated:
-
-
added missing tools to one abductor ship
-
-
farie82 updated:
-
-
Morphs examine text now stays true to the humanoid target they choose.
-
Cult constructs now show their examine text when you're next to it. Instead of on top of it.
-
-
-
24 September 2019
-
AzuleUtama updated:
-
-
Fixed misleading uplink description for chef's traitor knife.
-
Reorganises products in seed vendor.
-
Fixes Durathread mutating into more Durathread
-
-
Dave-TH updated:
-
-
Mob spawners will no longer sometimes send players to the void.
-
The ghosts inside possessed blades are now invincible and will not die to weird edge cases.
-
-
Evankhell561 updated:
-
-
mechs now start with a high-capacity power cell+
-
-
Fox McCloud updated:
-
-
Buckling has its own icon
-
Fixes Xenobio monkey shortcuts not working
-
Bodyscanners are similar to sleepers; interact with them by clicking on the scanner; there is no console anymore
-
Summon guns/magic is no longer free, but costs 2 spells points
-
Summon guns/magic makes 10% of the crew antags with the objective to collect guns/magical items and kill anyone who gets in their way
-
If a wizard (or admin) summons guns/magic, latejoiners to the round will also acquire summoned items
-
Wizard's hardsuit is now battlemage armor
-
Battlemage armor protects you from pressure of space (but not the cold), has no slowdown, and a moderate amount of armor, however, it has 16 shields to block incoming attacks
-
Can purchase additional charges for your battlemage armor for 1 spell point
-
Shielded hardsuits now show the shield on the mob
-
Abductors, Skeletons, Shadowlings, and Plasmamen never get hungry
-
Abductors, Skeleton, and Plasmamen can't taste anything
-
Wood Golems now have a diet and taste sensitivity much like Diona
-
Unathi are more sensitive to tastes
-
Adjusted the sensitivity of "sharp" and "dull" tastes a bit
-
Slimes are a simple mob subtype
-
using a bloodlust slime potion on a docile slime removes the docility
-
using a docility potion on a rabid slime calms them down
-
slime core removal surgery steps are now just scalpel->hemostat
-
Slimes have action buttons to feed on, evolve, or reproduce
-
Fixes beepsky arresting slimes (maybe it should be a feature....)
-
Fixes Seed Vault gene modder having limitations
-
Fixes not being able to extinguish some items
-
-
Ionward updated:
-
-
Fixed Tajaran fat sprites, they are no longer duplicates of their slim torso.
-
Fixed fat aqua jumpsuit only using one direction.
-
Fixed missing Lasagna icon.
-
-
Kyep updated:
-
-
The Hierophant club and warp cubes (lavaland loot) no longer allow you to teleport into or out of areas that are set to forbid teleports.
-
Fixed a small bug that caused coins named "syndicate coin" or "antag token" to both incorrectly appear as "valid coin".
-
-
Markolie updated:
-
-
Fixed naked equipment selection and reincarnation not working.
-
-
TDSSS updated:
-
-
all huds are the first option when ghosts cycle through huds
-
fixed brig door timers from announcing admin names when stopped via admin powers.
-
-
Ty-Omaha updated:
-
-
You can now silence the current midi with a verb in the preferences tab, without affecting your prefrence to hear midis in the future.
-
-
datlo updated:
-
-
Fixed clown changelings not losing comic sans on transformation
-
Clowns can now lose the clumsy and comic genes through DNA manipulation (but not mutadone)
-
-
-
22 September 2019
-
Evankhell561 updated:
-
-
Mech ID upload panels now come with [add all] and [delete all] options
-
-
Fox McCloud updated:
-
-
Fixes corpses/lying down mobs blocking projectiles
-
-
MarsM0nd updated:
-
-
can safely pick up nettles again
-
-
SteelSlayer updated:
-
-
Traitor and mindslave status is handled in a datum instead of the mind
-
You can no longer use a mindslave implant on a person with no mind
-
Adds the ability for admins to de-mindslave somone through the traitor panel
-
De-traitoring malf AIs via the traitor panel removes all instances of their Law 0
-
De-traitoring malf AIs via the traitor panel removes their ability to still state laws over the syndicate channel
-
De-traitoring malf AIs via the traitor panel removes their ability to shunt to hacked APCs
-
Unemagging borgs via the traitor panel properly removes their syndicate laws and gives them the crewsimov lawset
-
Unemagging borgs via the traitor panel who did not have a module selected does not cause a runtime anymore
-
-
TDSSS updated:
-
-
Just slight gloves refactor, shouldn't impact anything in game.
-
-
-
21 September 2019
-
AzuleUtama updated:
-
-
The Captain's rapier can now be assigned as a theft objective.
-
Slime extracts and plasma tanks have been removed as theft objectives.
-
Document trading no longer counts towards a traitor's total number of assigned objectives.
-
Fixes a grammar error with the ambulance and slightly misleading description with the combat gloves.
-
Headpat gloves now inherit their click speed from the North Star gloves and are no longer as fast as before.
-
Sarin gas grenades no longer purchasable for nuke ops. balance: Grenadier belt now contains a sarin gas grenade. balance: Tactical medkit's hypospray tweaked to contain chems better for dealing with newcrit. balance: C20 bundle increased in price to 18TC, contains an additional clip of ammo. balance: Medical bundle increased in price to 20TC, Donk LMG removed, replaced with medbeam gun and magboots.
-
Fixed some minor spelling/grammar errors with synthflesh patches and sarin gas grenades.
-
R&D Console no longer has a default design called 'Name' show up in the mining category.
-
Syndie and Binary keys now use their own sprites rather than the default ones.
-
-
Couls updated:
-
-
Romerol virus that requires two traitors to team up to purchase
-
zombies that have a slow but steady health regeneration and cannot be killed permanently outside of decapitations and removal of the tumor in the brain
-
blood no longer stacks on itself endlessly
-
fixes footprints stacking
-
removes zombie from the secondary language list
-
hotkey menu option in the dropdown works correctly now
-
configurable limit to amount of monkeys that can be spawned by monkey cubes
-
handle_death is passed the gibbed variable
-
spec_death replaced with handle_death in romerol
-
you no longer hit yourself with things you throw
-
missing arguments in some procs
-
some macros that were defined twice
-
recycled monkeys were not being subtracted from the monkey cap
-
-
Dave-TH updated:
-
-
Fixes some vending machines (namely miner nanomeds) from adding all of their product twice.
-
Magical weapons can now be properly dual-wielded.
-
Fixes the description of energy shields, which said they block things that they do not.
-
Crayon drawings can stack again.
-
Crayons can no longer draw on multiple tiles at the same time, sorry octo-artist!
-
Fixes the lack of cooldown on attacking light fixtures.
-
Examining an air analyzer now informs you about its lesser-known function!
-
-
Emanthealmighty updated:
-
-
Updated the netherworld creatures' sprites.
-
-
Fox McCloud updated:
-
-
refactored gloves of the North Star to be more adminbusy
-
Adds Gloves of Headpats to the pet vendor as a premium item
-
Refactors the very core and soul of SS13 and enhances the code that powers it
-
Bible fartgibbing is now a form of suicide
-
Fixes mice coming back to life
-
Fixes nurse spiders not wrapping things
-
Fixes spiders not spazzing out
-
Simple mobs will now attack everything in the vicinity instead of just specific object types
-
Gutlunches now eat internal organs
-
ranged guardians don't rapid fire anymore, but have a lower cooldown on attacks
-
Fixes some turf underlays not working
-
adds in a wooden hatechet and rake to the ashwalker base; replaces the regular bucket with a wooden one
-
Fixes some blank tastes
-
Fixes not being able to brew fruit wine
-
Fixes poor TG copy pasta code that caused hundreds of runtimes
-
Reduces round-start lag
-
Fixes certain PDA cartridges causing insane performance loss
-
Carp Migration event no longer deletes the carp when it ends; they will continue to stick around the station
-
Personal crafting now has subcategories
-
Finishing crafting an item puts it in your hands instead of on the floor
-
comments out romerol (much like zombies, it will rise again, don't worry!)
-
zombies are high and lower pressure immune in addition to immune to heat and tox damage
-
Ian now has persistence; if he's killed, he'll start over life as a puppy--if he lives to a very long old age, he'll get a unique sprite
-
Pugs will now yipe on death and can bark
-
Adds new dog mob; a generic black dog
-
Foxes are now a dog subtype
-
Can manually yelp as a dog
-
All dog subtypes can now chase their tail and be given pats and pets. They all can additionally eat (and taste!) food
-
Nar-Sie will absolutely not tolerate sacrificing doggos
-
Ripleys are slightly faster on station, but dramatically faster on Lavaland
-
Mech mining drings can no longer drill through floors; they also don't just drill once. After a short delay, they'll attempt to drill the target, repeatedly.
-
Mech mining drills no longer instantly knock out mobs; if the mob is dead and has over 200 brute, the drill will attempt to harvest or gib the mob; can also disembowel
-
Mech plasma gun has a lower cooldown
-
Mining scanners apply a much brighter and visible overlay; mining a turf will now instantly clear the overlay
-
Mining mech (the one that's a lavaland find) has a partially depleted cell; it'll also no longer have multiple mining tools on it
-
Fixes null animal type with regards to pugs
-
Legion body loot adjusted; may find rare alternative mining belt or primitive one; bone bracers also show up on Ashwalkers; mini pickaxe spawn also possible
-
Large legions can damage objects
-
Small legion skulls no longer block mob movement
-
Basilisks are now gold core spawnable
-
Gutlunches no longer produce adult version of themselves, but have babies that grow into gutlunches
-
Mining belts can now hold pillbottles and shovels
-
Goliath cloaks hold different items now; more inclined to what Ashwalkers would use and not miners
-
Swarmer megafauna now has its proper GPS
-
Can't kill mining fauna by overheating them
-
new sprite for the Hierophant
-
Refactored tendrils; they won't show up on health HUDs anymore
-
Fixes Tendrils not emitting light
-
Fixes tendrils not changing the terrain around them
-
Fixes being able to exploit vending machines by deconstructing then reconstructing them to get additional items. Get an additional restocking units from cargo you filthy dirty exploiters
-
All vending machines require only a single restocking unit to build
-
Clothing, NanoMed, Wallmed, Vendomat, EngiVend, NutriMax, Megaseed Servitor, Sustenance Vendor, Dinnerware Vendor, Cart Tech, Robco Toolmaker, soviet BODA, security tech, and modular PC vendors are all now makeable/restockable
-
Most vendors can be damaged by brute force (Nanomed, wallmed, and youtool are notable exceptions)
-
Most restocking units can be ordered from cargo
-
Removed snowflakey laptop vendor
-
Adds in new laptop+tablet vendor; don't expect it to have as much (ask science for upgrade parts!)
-
Sustenance vendor has a new set of contraband if prisoners can actually hack the thing
-
breaks up the clothing restocking unit cargo pack from a single pack into 4 separate packs, 15 points each
-
Fixes Megafauna spawning near the base
-
Fixes lava rivers not forming
-
Upped the labor mineral spawn rate
-
Removed the ability to find random code-locked crates when mining
-
Watcher Icewing blasts will briefly freeze you
-
Fixes too much detecting corgis
-
Tweaks a few reagents tastes
-
fixes being able to taste metaphorical salt
-
nutriment no longer restores blood
-
Nuke ops can no longer advanced syndie magboots
-
Fixes an inconsistency with chameleon kit pricing--it was only 2 TC, making the no slip syndicate shoes worthless; price is now 4 TC
-
operatives pay 2 TC more for the no slip syndicate shoes and the chameleon kit
-
Wizard hardsuits no longer come with magboots
-
Syndie magboots are nuke ops only
-
Can purchase no slip shoes from the uplink instead of a full chameleon kit
-
Operatives can purchase no slip syndicate shoes
-
No slip shoes can protect against atmos pushing
-
removed most round-start magboots with the exception of EVA, atmostechs, CE, and engineering hardsuit dispensers
-
Fixes carp not being a threat to the station due to killing themselves
-
Fixes being able to exploit simple mob AI so it kills itself in an atmos death blender
-
vent and scrubbers work far more efficiently and quickly now
-
Fixes wideband on scrubbers constantly resetting itself
-
Portable scrubbers far more effective
-
Flamethrowers far more effective
-
Nanofrost twice as expensive
-
regular syndicate borgs don't have magpulse by default
-
Atmos pushing completely refactored; it'll still push you frequently and push items around frequently, but it won't throw you. Depending on how many dense objects or turfs are around you to "grab onto" will determine how effective atmos is at pushing you around. Does not alter the speed at which LINDA runs.
-
Plasma glass shards do less damage when attacking, but slightly more when stepping on them
-
Spears made out of plasma glass do slightly more damage
-
Light replacer can now be used in-hand to attempt to reload empty lighting fixtures around you in addition to showing how many lights it has
-
Light replacer needs less shards to increment bulbs
-
Updates moonflower, sunflower, novaflower, and pineapple sprites
-
Adds in Garlic
-
Fixes a few issues with incorrect values from the wine PR
-
Can now grow and extract the reagents/traits of Lavaland flora
-
Slightly tweaks soybean oil production on soybeans
-
Adds amusing garlic suicide
-
Ash Drake reworked; it's much more powerful now and has a diverse set of attacks--its fire breath is more random, it moves faster, it can turn the ground into lava, and once it's lower on health, will seal you into an arena and make you play the "only one turf is safe; stand on it or suffer" mini-game
-
Bubblegum is now much more difficult; instead of just spraying blood at you and attempting to endlessly charge you (walking backwards essentially counters it), it's now faster, engages in zig-zag attacks, uses a hallucination multi-attack, and can rapidly melee attack you in range
-
Fixes megafauana endlessly attacking dead mobs
-
Blood drunk Colossus, and Ash Drake made to be more player friendly if they control the fauna
-
Adds in Space dragon; a very weak version of the Ash drake which can't swoop, but can still breathe fire--has a spell that whips you back with its tail, too (not currently used anywhere)
-
The real Roman shield and real Roman helmets in the Autodrobe have been replaced by fake, armorless, varieties
-
Hierophant has been updated--it'll be a bit tougher and will attempt to trap you if you run for it.
-
Heirophant is no longer a weird bird thing, but a massive, indecipherable piece of machinery that will make you dance to ITS tune
-
Hierophant club is weaker up front, but becomes stronger the lower health you are
-
Fixes tendrils spawning inside ruins
-
Fixes light replacers breaking/hitting lights
-
Fixes blood drunk buff not making you slow immune
-
Regenerative core will give you 1 minute of slow immunity on application
-
carp sprites now support a wider range of colors
-
Megacarp names randomized in addition to their stats
-
Adds new friendly life reaction (strange reagent + synthflesh + sugar + heat)
-
Life reaction amount of critters spawned varies with created volume
-
Can now spawn the xeno maid, lightgeists, and bees with slimes cores/life
-
can no longer spawn the Shamebrero penguin with slimes cores/life
-
Adds new EVIL crab; is a "hostile" slime core/life mob
-
simple Xenos are a bit more powerful
-
Butchering simple Xenos now leaves a Xeno hide; use it to make a Xeno costume
-
Fixes spriteless dog
-
Fixes being able to spawn Proc with slimes cores/life
-
Fixes Blooddrunk being a flying mob
-
can move dense objects around corners
-
Removes unused, highly buggy VR code
-
Completely transitions to Lavaland for all maps. The mining asteroid and it's related bits are removed
-
Vox reworked
-
Vox are no longer spaceproof
-
EMP's no longer wreck cortical stacks
-
Vox cortical stacks are their brains; there's no longer two separate organs for Vox brain+cortical stack
-
Vox are immune to decay and will not skeletonize
-
Vox internal organs will never accumulate germs or decay, even when they're outside a Vox's body
-
Vox external organs do not accumulate germs when attached to their body
-
Vox have silent footsteps
-
Vox can process BOTH organic and synthetic reagents
-
Diona no longer decay into skeletons
-
Can now pick the species you want to play as for lavaland ghost roles
-
Golems have been buffed.
-
Golems are faster, better protected against damage, and have limbs that cannot break or be dismembered.
-
Golems are no longer virus immune
-
Golems can now wear labcoats and boxing gloves
-
Fixes golems being able to be healed/injected on parts other than the chest
-
Having a robotic chest allow you to wear an ID, PDA, and belt without a jumpsuit. Having a robotic right leg allows you to use your right pocket without a jumpsuit; same for your left
-
stepping on glass tubes now shatters them; can trip you up if you aren't wearing shoes
-
Stepping on a D4 will deal between 1 and 4 damage to you if you aren't wearing shoes and trip you up
-
skeletons have built in pierce immunity
-
-
Ionward updated:
-
-
Greys, Unathi, Tajaran, and Vulpkanin now have sprites for Lavaland reward hardsuits (Wizard, Elite Syndicate, and Paranormals), Biosuits, Voidsuits, and Syndicate Soft suits.
-
Plasmamen Librarians now have visible helmets.
-
Atmos Hardsuits now have inhand sprites again.
-
Added new uniform and hat to the AutoDrobe, the Rhumba outfit.
-
-
KasparoVy updated:
-
-
Tajaran characters can now have the tiny & short tails (plus marking).
-
Adds a striped tail marking for Tajara derived from the sriped/wingler body accessory to allow more flexible colouration.
-
Renames Vulpkanin alt. tails for brevity and easier keyboard navigation.
-
-
Kyep updated:
-
-
Fixed bug that made the syndicate depot impossibly difficult.
-
Various improvements to syndi depot, such as use of plastitanium walls, and nerfs to some cheese strategies.
-
Ported TG's simple_human.dmi, a sprite file of humanoid sprites (including syndicates).
-
Added a few extra syndi sprites from FoS.
-
fixed an issue with keyboard input
-
Brig timers now display the job of brigged people. E.g. "Joe Schmoe (Chemist) was incarcerated" as opposed to just "Joe Schmoe was incarcerated".
-
Brig timers now notify a person's boss via PDA when they are incarcerated. E.g. if a chemist is temporarily brigged, the CMO is notified of the brigging via PDA.
-
-
Markolie updated:
-
-
Guardian communciation now longer shows up to players in the lobby.
-
-
Mocha-Not-Latte updated:
-
-
Fixes #12354
-
-
Shadow-Quill updated:
-
-
Fixed ATM withdrawals doubling.
-
Fixed Fore Port Solars' APC not charging.
-
Fixed a typo in admin gloves of rapidness.
-
Plasma cutters will no longer eat plasma if you try recharging a full gun.
-
Blobs now get a audio notification roundstart (like traitors do.)
-
-
SomeSortaSquid updated:
-
-
Karma purchases no longer loop infinitely, leading to repeated purchase prompts or "You do not have enough karma!" message after successful purchase.
-
-
SteelSlayer updated:
-
-
The AI and magistrate get bold text when the "louder command members" telecomms setting is on
-
Command members will get the first letter of their radio message auto capitalized when the "louder command members" telecomms setting is on
-
Malf AI's overload machine & override machine action button behavior is changed to a point and click style ability.
-
Added some new mouse pointer icons for the machine overload and machine override abilities
-
The "Show Player Panel" verb is now right click only
-
The "C.M.A. - Admin" verb is now right click only
-
The "C.M.A. - Self" verb is now right click only
-
The "Check Contents" verb is now right click only
-
The "Freeze" verb is now right click only
-
The "Freeze Mech" verb is now right click only
-
The "Jump to Turf" verb is now right click only
-
The "Update Mob Sprite" verb is now right click only
-
The "List SSDs" and "List AFKs" verbs have been combined into one verb named "List SSDs and AFKs"
-
The "Resolve All Open Mentor Tickets" verb has been moved inside the mentor ticket interface window
-
The "Resolve All Open Admin Tickets" verb has been moved inside the admin ticket interface window
-
Increases the width of the new "List SSDs and AFKs" window a bit
-
The gravitational catapult no longer pushes ghosts when used
-
Fixes a runtime preventing walls from being repaired properly
-
Adds the ability to repair and remove bullet holes from reinforced walls that have no structural damage
-
-
TDSSS updated:
-
-
local gps signals, visible only on the same z level
-
lavaland mob signals were made local, reducing gps clutter
-
Objective to abductors to not disrupt crew too much.
-
healing fountain lavaland ruin now correctly heals
-
lowered attack log level of self-harm
-
certain harmless chems and food have reduced attack log logging levels
-
the most grave of wrong tips
-
The uplink dart gun now comes with some syringes to use with it.
-
-
Terilia updated:
-
-
stat_attack from unconscious to dead
-
added new headcrabs (poison and fast)
-
added new headcrab sounds for the poison headcrab and the fast zombie
-
-
TheMadTrickster updated:
-
-
fixed wonky/bugged sprites for custom guitar and hair gel
-
new improved clean sprites for custom items
-
old messy sprites for custom items
-
-
TheSardele updated:
-
-
Changes the attack log setting required to have the blood-drunk miner buff actively log to all attack logs.
-
-
Ty-Omaha updated:
-
-
Headpat gloves added to arcade machine prizes
-
Minor ban evasion update
-
Autonote for manual bans removed
-
SSD players no longer drown in shallow water
-
Admins can now autoreply with common answers to common questions / issues.
-
Opening an adminhelp/mentorhelp ticket will play a sound
-
Adminhelp ticket information color changed from neon green to a more toned down green
-
Global admin midis will now silence lobby music for those who have midis enabled.
-
Adds "Man Up" to autoreply
-
Autoreponses now show up as the last admin response in tickets
-
Fixes an issue where autoresolve was appearing in mentorhelps to mentors
-
Resolve button on adminhelps and mentorhelps work again
-
Fixes reversed logic in autorespond confirmation alert
-
Removed custom admin event info that only admins could view due to confusion with the regular non-admin verb.
-
-
datlo updated:
-
-
Added the Banana Touch and Mime Malaise spells to the Wizard spellbook.
-
Station goal crates now come in engineering crates.
-
Replaced the red emergency toolbox in hermit ruin by a regular blue toolbox.
-
-
farie82 updated:
-
-
Hoodies now work like they do in TG. Less abuse of NO DROP, more better
-
Welding a tile away now gives a more useful message when doing so.
-
Admins now don't get spammed by hugs.
-
-
kazboo updated:
-
-
added a nice metalic alarm sound for when the nuclear self-destruct is activated on the station.
-
candle boxes on the station are now properly filled
-
-
variableundefined updated:
-
-
Multiple food now have their own tastes
-
Corgi and mice can now taste food
-
Hallucination causes you to taste strange things
-
Nutriments now carry over the tastes of food
-
A quick resolve button to adminhelp and mentorhelp message!
-
Config option to let gamemode ignore the number of required players.
-
Hit_reaction proc has been refactored.
-
Flamethrower and grenade detonation by shot is now logged.
-
Refactored wooden chair so placing them won't make you see normal metallic chair anymore.
-
Contribution guideline has been updated. No in game changes.
-
Github pull request template has been changed
-
Officer starter pack to cargo. For 30 cargo points you can equip an officer just like an officer closet! Backpack not included due to budget cut.
-
-
xProlithium updated:
-
-
Replaced link to CA (check antags) in adminhelps, tickets, and adminmoreinfo with a link to TP (traitor panel)
-
Altered CA to TP for prayers and adminpms.
-
-
-
30 August 2019
-
AffectedArc07 updated:
-
-
Fixes the changelog
-
-
Arkatos updated:
-
-
Added new icon for Charge spell
-
Added new icon for No Clothes spell
-
Added new icon for Wizard spellbook
-
Added new animations to 10 single-use spellbooks
-
Added new sprite for Bottle of Tickles
-
Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
-
Fixed an issue where Bottle of Tickles did not properly refund
-
Fixed an issue with alpha layering on Bottle of Ooze sprite
-
Very slightly adjusted brightness of the Boo! ghost spell icon
-
Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
-
Polymorph can now turn a mob into Syndicate medical or saboteur modules
-
Mobs made via polymorph into borgs are now unbounded free borgs
-
Repulse spell cost decreased from 2 to 1
-
Lighting bolt spell cost decreased from 2 to 1
-
Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
-
Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
-
Improved descriptions and wording regarding Wizard spellbook and Wizard spells
-
Traitor AI now uses action buttons for its malfunction abilities
-
-
AzuleUtama updated:
-
-
Adds false-bottomed briefcase from VG.
-
-
Couls updated:
-
-
Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
-
Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
-
DUAL WIELDING
-
new chatsubsystem from TG!
-
Update issue templates to latest version and clean up the current template
-
mining shuttle warning message and delay before launching
-
cardboard boxes are no longer sonic speed
-
shuttle timers now get set properly
-
-
EmanTheAlmighty updated:
-
-
Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
-
Blobbernauts and blobs can now communicate with each other.
-
Blobbernauts now regenerate health overtime when standing on blob structures.
-
Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
-
-
Emanthealmighty updated:
-
-
The poll to play as a blobbernaut now lasts 10 seconds from 15.
-
Blobbernauts no longer chase after people while players are being polled to play as one.
-
-
Fox McCloud updated:
-
-
Plasmamen dramatically overhauled.
-
Plasmamen can be cloned without burning to death in the clonepod
-
Plasmamen no longer start with spacesuits
-
Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
-
Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
-
Plasmamen take 50% extra brute and burn
-
Plasmamen are immune to radiation
-
Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
-
Plasmaman helmets now have built in welding goggles
-
Plasmaman karma cost lowered from 100 to 45
-
Reworks Diona
-
Diona bleed (call it chlorophy; it's green)
-
Diona Breathe (plants do need to exchange gas after all)
-
Rad Immunity Removed
-
Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
-
Diona no longer have unbreakable bones (wood can crack ya know!)
-
Diona are no longer space proof
-
Diona are more vulnerable to fire and heat damage
-
Diona weakness to weedkiller dramatically nerfed
-
Diona now use Newcrit
-
Diona are no longer slow
-
Diona can wear spacesuits
-
Fixes stun absorbing not working
-
Fixes parallax insane setting not doing anything
-
Ores can be destroyed by devastating explosions
-
silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
-
drills slightly slower, but diamond drills slightly faster
-
Spade is the same speed as a shovel
-
Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
-
can use a hivelord core in your active hand to apply it to yourself
-
soulstone in the abandoned locked crates can now be used by anyone
-
Adds firelemon seeds to the abandoned locked crates as potential loot
-
Hardsuits have an integrated helmet; you no longer have to attach helmets
-
Toggling up/down helmets is now done with an action button
-
can no longer attach magboots to a hardsuit
-
Hardsuit base melee armor increased from 10 to 30
-
Security and HoS hardsuit melee armor increased by 5
-
HoS hardsuit helmet armor matches his hardsuit
-
CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
-
Elite syndicate suits can't be acided
-
Fixes stuns and weakens related to reagents
-
Fixes the displayed cost of Plasmamen
-
Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
-
Removes mining carbon dioxide jetpack
-
Can no longer use jetpacks in your suit storage slot
-
Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
-
Fixes random singularity releases from the grid check event
-
loadout costs for most things cut from 2 to 1
-
Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
-
moved hipster glasses from donator to general glasses
-
Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
-
Removes access based security barriers
-
Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
-
can tear up bedsheet and gauze to get cloth--requires a sharp object
-
Fixes plasmamen atmos techs not getting their proper suit
-
Adds in a loom, craft one out of 10 wood
-
Adds in cotton and durathread cotton to botany to grow
-
Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
-
Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
-
Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
-
Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
-
adds a whole range of beanies, find them in the clothing vendor or make them yourself
-
Updates the cowboy boots sprites
-
Unironically fixes about several thousand runtimes
-
Fixes jackets not keeping you warm
-
Chefs are now trained in the art of Close Quarters Cooking
-
Adds the Book of Babel as tendril loot
-
Adds Jacbo's Ladder as tendril loot
-
Fixes fungus, blood, and graffiti not showing up on a wall
-
Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
-
Fixes baseball bats throwing anchored things
-
Fixes blood drunk buff
-
Fixes using a crusher on a trophy to equip it causing you to drop the crusher
-
refactors lazarus capsules; no real behavioral change
-
Fixes being able to revive megafauna with strange reagent
-
-
Fox McCloud and FullOfSkittles updated:
-
-
Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
-
Fixes telebacon not properly acting as...well, a bacon beacon
-
-
FreeStylaLT updated:
-
-
Added an Engine Picker, which uses new engine beacons.
-
Replaced the current two engine generators with one engine beacon.
-
-
Ionward updated:
-
-
Drask crewmembers now have properly fitting shoes.
-
Fixed some minor issues in Drasks uniforms
-
non-humans now have proper sprites for durathread goods
-
-
KasparoVy updated:
-
-
Adds sprites for all Vox & Armalis earwear.
-
Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
-
You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
-
Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
-
Fixes an issue preventing the species-fitting of earwear.
-
Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
-
Picking up uniforms no longer renders a default grey jumpsuit on Vox.
-
Resolves an issue causing shining eyes to be rendered darker than intended.
-
Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
-
Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
-
Non-shining eyes render the proper colour again.
-
-
Kurgis updated:
-
-
Beepsky now bumps around on its wheels when patrolling for crime.
-
-
Markolie updated:
-
-
A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
-
Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
-
The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
-
A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
-
Outfits now support accessories and internal boxes.
-
The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
-
Water coming from sinks and certain water effects is now 10C instead of body temperature.
-
-
Shadow-Quill updated:
-
-
[Meta] Added buckshot and slugs to armoury.
-
[Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
-
[Meta] R&D doors now has proper access requirements.
-
[Meta] Added RCS and telepad to cargo.
-
[Meta] Disposals sheet stacker and conveyor belts now works properly.
-
[Meta] One-way airlocks added in Medbay/Brig.
-
[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
-
AIs not being able to restore their own power if in an area with an APC.
-
Fixed being able to talk in OOC under certain circumstances if it's disabled.
-
Lockers can no longer move around anchored mobs.
-
-
SteelSlayer updated:
-
-
You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
-
The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
-
A cable adding sound gets played when you add wires to create a terminal for a SMES
-
Rapid pipe dispensers can now place disposal sorting pipes
-
When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
-
Added a destination tagger to the atmosheric technician locker
-
Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
-
Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
-
IV bags are able to transfer their contents to other containers by clicking on them with the bag
-
Adds a handheld defibrillator to the paramedic EVA closet
-
You can insert magazines into L6 SAWs again
-
Removed one of the high capacity tanks in hydroponics
-
Added a disk compartmentalizer to hydroponics
-
Delaying round start actually delays round start again
-
-
Terilia updated:
-
-
added headcrabs
-
adjusted the path's for headslugs. They are not called headcrab anymore
-
-
TheSardele updated:
-
-
Removes the ability of obese people and those with matter eater to swallow others.
-
-
Ty-Omaha updated:
-
-
Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
-
-
datlo updated:
-
-
Added ashstorm immunity to titanium and plastitanium golems.
-
Added lava immunity to plastitanium golems.
-
Bananium golems now slowly waddle around.
-
Uranium golems now properly irradiate nearby mobs that arent rad immune.
-
Tranquillite golems now properly get their miming powers.
-
Added the Clown and Winter biodomes as possible lavaland ruins.
-
Update a changeling error message to be clearer.
-
-
farie82 updated:
-
-
Items with NODROP that are dropped now lose the flag if they didn't get created with it
-
Adds tip text to the examine text of the ambulance trolley about how to attach it
-
Adds tip text to the nuke when trying to use the NAD before deploying it
-
Adds tip text to the fire axe cabinet about how to lock/unlock it
-
Adds tip text to airlocks if they have a note on them about how to remove the note
-
Can't put the NAD in the nuke now when it has the NODROP flag
-
Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
-
Can't put a nodrop fire axe in fire axe cabinets now. Duping them
-
Implants like the IPC charging work again. They won't get deleted after first use
-
-
variableundefined updated:
-
-
A proc's name got changed. That's it
-
-
-
23 August 2019
-
AffectedArc07, Keekenox, Floyd/Qustinnus updated:
-
-
P A R A L L A X (That fancy space thing)
-
Adds a new Parallax layer that resembles Lavaland (Lava Planet), it spawns on a random location near the station. You need your parallax on high to see it.
-
-
Arkatos updated:
-
-
Added colored pillbottles
-
Added an option to change color of the pillbottles to ChemMaster3000
-
Added new description to patch packs
-
Jump to Node ability now shows a location of each Blob node
-
Added SlimeHUD when playing as a slime. This means slimes will have their own unique health doll and pull icon.
-
Action buttons can now be dragged onto each other to swap places
-
Fixed a case where dragging locked action buttons could result in white tooltip over the screen
-
-
AzuleUtama updated:
-
-
The Traitor thermal glasses and chameleon security HUD now use the updated chameleon code. balance: Traitor thermal glasses will no longer cause eye damage when hit with EMP.
-
-
Citinited updated:
-
-
Removes the big pipe dispensers from atmospherics, you can still find them elsewhere.
-
-
Couls updated:
-
-
After many complaints about being stuck in medbay. NT has modified all the airlocks on the station to allow leaving certain departments without requiring an respective ID. This new modification is indicated by a white light near the airlocks in the direction of unrestricted access.
-
New unrestricted access can be built by NT engineers through modification of the airlock electronics.
-
hit effects!
-
hit effect sprites for lasers, bullet hole and dent decals for walls
-
mice now have a very low chance of chewing through wires, this kills them if the wire is powered
-
You can now homerun things thrown at you with a baseball bat!
-
new baseball hit noise, new baseball sprite
-
there are much less one-way airlocks on station
-
-
DoctorDrugs updated:
-
-
removed the ability to eat the divine vocal cords
-
-
EmanTheAlmighty updated:
-
-
The AI can now change its intent by clicking on the new on-screen button or pressing 4 to switch to help or harm.
-
The AI can now toggle airlock safeties instead of toggling door bolt lights by pressing middle mouse.
-
-
Fox McCloud updated:
-
-
Majorly updates lavaland
-
Miner starting equipment altered. They now start with a kinetic accelerator
-
Miners start off with a mini pickaxe
-
Adds in the boxed implant kit, regular shelter capsule, and mining drone passthrough upgrade to the mining equipment vendor
-
re-ordered the equipment vendor, so things are grouped together more logically
-
Added a number of new kinetic accelerator upgrades acquirable through tendril chests
-
Mining bot now uses an actual kinetic accelerator as opposed to a "Look alike"; you can upgrade its internal gun with various kinetic accelerator modkits.
-
Sentient mining bot nerfed; you can no longer apply the armor or melee buff to them; offset by the fact you can upgrade their kinetic gun.
-
Indoor pressure mod removed from R&D and made into a miner traitor item
-
Resonators have an increased amount of fields and do more damage in low pressure. Additionally, if you place a field on a tile that already has a field, it'll cause it to detonate early
-
Plasmacutter no longer does increased damage in low pressure, Advanced plasma cutter does slightly more base damage but has a bit less range. Price has been cut at R&D
-
removed the AoE Mob+Turf upgrade for mining pods
-
Fixes ripleys being slow on lavaland
-
Fixes walking on lavaland sounding like walking on metal plating
-
Adds in kinetic crusher trophies
-
Kinetic crusher can be wielded/unwielded (but you can't attack with it unwielded)
-
Adds the HECK suit as Bubblegum loot
-
Adds the kinetic accelerator bounty mod as Tendril loot
-
Add fulton extract packs to the mining vendor; rescue precious valuable or dead miners!
-
Adds mini-fans to the mining, engineering, and security shuttles
-
Adds a number of primal recipes: rake (cultivator), wooden bucket, firebrand (long burning match), and bone bracers (armored arm protection that goes on your glove slot)
-
Can attach bayonets to C20rs, bolt action rifles, security auto-rifles, and kinetic accelerator; harm intent to stab with them
-
can craft ore boxes out of wood
-
Skull helmets are now proper helmets
-
Survival autoinjectors tweaked
-
Survival autoinjectors have 15 units of teporone in them
-
Survival autoinjectors have double the epinpehrine and weak omnizine instead of saline glucose.
-
lavaland extract altered; it no longer heals tox or oxy, and heals slightly less brute and burn, but has nearly halved the metabolization rate and has a less harsh overdose
-
Fixes airlocks spamming their open and close when you stand in them
-
Fixes overriden door timers not working
-
-
Fox McCloud and FullofSkittles updated:
-
-
Changes the Venus Human Flytrap sprite
-
-
Ionward updated:
-
-
Adjusted Greys uniforms and backpack sprites.
-
Added a bunch of Drask masks and glasses.
-
Added God Eye sprites for Greys, Drask, and Vox.
-
-
JKnutson101 updated:
-
-
Issue where Emergency NanoMed Vendors required Medical ID to Access.
-
Added the ability for cyborgs with zero battery to use the 'succumb' verb.
-
-
Markolie updated:
-
-
Players now have thirty seconds instead of just five seconds to select if they want to be somebody's butler through a die of fate roll.
-
The Netherworld portal is now properly destroyed upon being killed. In addition, its max health is now equal to its starting health.
-
The iron ore sprite that shows up when using the miner scanner no longer has a background, making it blend in better with the actual rock.
-
Tightening the bolts of a falsewall now works properly.
-
Deconstructing plating now requires it to be unfastened using a screwdriver first, in order to prevent it from being accidentally deconstructed with a welder.
-
-
Quantum-M updated:
-
-
Minor grammar edits to the text that tells you that your thirst is dealt with but no blood power is given. balance: Vampires are no longer able to drink get power from ckeyless humanoid monkeys, they will now need to hunt down actual characters with ckey to get power.
-
-
Shadow-Quill updated:
-
-
Mass drivers now need two rods/cable coil instead of three to construct.
-
The RD's office door can now be opened by the RD, instead of by just the Captain.
-
Science lockdown can now only be (de)activated by the RD, instead of any scientist.
-
Using a health analyzer in-hand will switch the verbosity.
-
You no longer have to unscrew a plating to repair it.
-
The shivering symptom in virology now properly chills people.
-
-
SteelSlayer updated:
-
-
Wizard rounds now end if all wizards and apprentices are either dead, inside cyborgs, or in MMIs
-
Re-enabled the wizard's hud. Wizards can now see their own antag icon along with seeing other wizard's and apprentice's icons
-
When a cult sacrifice target leaves the round via cryo, the game will reassign a new target for them
-
Added an alarm sound that plays for cultists when their sacrifice target leave the round via cryo
-
When a cult sacrifice target leaves the round via cryo, the game will update every cultist's notes to reflect the change
-
Adds a new verb named "Toggle Health Scan" to the ghost tab. While toggled on, ghosts can perform health scans on humanoids and cyborgs by left clicking on them
-
-
TDSSS updated:
-
-
syndicate fax machine to lavaland syndie base.
-
syndicate lavaland base self destruct now requires syndie access.
-
moved headsets in lavaland syndie base.
-
Gave the HoP fax long-ranged faxing capabilities.
-
midround event spawned xeno larva now need less time to grow up and evolve.
-
cult talisman got unique icons to tell them apart
-
mining hardsuits come with helmets now again
-
-
Tayyyyyyy updated:
-
-
Whether you join the ERT is no longer determined by how fast you click "yes" on the prompt.
-
Drag and drop support and 20 seconds to pick ERT role instead of 15
-
Fix extra newline after field and disable Github Flavored Markdown in papers (normal markdown still works)
-
autogenerated papers no longer appear as HTML code
-
message window links added to PM send receipt
-
Many shuttle flight directions fixed
-
-
TheSardele updated:
-
-
All-In-one Grinders can now be constructed and upgraded
-
All-In-one Grinders now produce more reagents when upgraded.
-
Icon for cybernetic eyes
-
Sleeping while drunk no longer makes you more drunk.
-
-
dovydas12345 updated:
-
-
Fixes being able to pick up chairs and stools when you have items in both hand or when you don't have hands.
-
Adds a ERT shuttle console which is accessible to ERT members
-
-
farie82 updated:
-
-
Rigging a crate now doesn't delete your coil stack anymore but instead uses 15 of it. Borgs can use it safely again
-
-
kazboo updated:
-
-
adjusts the hierophant blast layer to make for it to always be below the effect. this should be the case already due to mouse_opacity, though for some unknown reason, it just doesn't work sometimes, so this should fix it.
-
-
-
12 August 2019
-
AffectedArc07 updated:
-
-
Panic Bunker
-
-
Allfd updated:
-
-
Panthers can now see in the dark.
-
-
Arkatos updated:
-
-
You can ctrl-click any action button to lock/unlock its position
-
All actions buttons now start with their position locked
-
-
Citinited updated:
-
-
Mappers have a new tool that creates a fully functional cycling airlock.
-
-
CornMyCob updated:
-
-
The cursed heart you get from necropolis chests is now the one that heals you.
-
-
Couls updated:
-
-
Diagonal movement
-
Input subsystem(numpad targetting, press numpad 8 multiple times to target eyes and mouth, numpad 6 or 4 to target arms and press them again to target hands and numpad 1 or 3 to target legs and press them again to target feet) taken from https://github.com/tgstation/tgstation/pull/32751
-
change confused status to have you move diagonally randomly in the direction you're headed if not too confused(now you can drunkenly walk down the hall)
-
clients are now children of datums like everything else in BYOND taken from https://github.com/tgstation/tgstation/pull/20394
-
AZERTY and numpad targetting preferences
-
Reworks the biohazard event to have a chance of giving a randomized advanced disease with 6 varying symptoms instead of a preset disease.
-
change how bone breakage is calculated
-
can now butcher koi for salmon meat
-
adds a line to alert people as to why they're not getting blood from the monkeys
-
The vampires are finally off their monkey diet, theycan now suck blood from players and humanized monkeys
-
Symptoms are now correctly generated for level 7 biohazards
-
Borgs can now cycle modules with X again
-
Ahelp message is less confusing
-
F2 (say) F3(ooc) F4(me) buttons have been restored tweak:when numpad targetting is off you can use numpad 1-4 to change intents tweak:pressing shift before any of the intent buttons doesn't change intents(for people with shift+1-4 macros) tweak:backspace now sets the focus to the chat bar
-
fixes the runtime caused by running keyloop for clients
-
Preferences not saving properly
-
issue with preload_rsc
-
Restore hotkey mode
-
Q no longer drops items as a cyborg on AZERTY mode
-
Automatically offload ore you're carrying to an orebox you're dragging
-
typing indicators show up again
-
TG waddle component, clowns can now optionally waddle, penguins always waddle. Ctrl Click clown shoes in hand to toggle waddling
-
Added invismin macro back to F9
-
stealthmin macro removed from F9
-
-
Crazylemon64 updated:
-
-
Fixes a bug that would cause ghosts to teleport their bodies sometimes
-
-
Dave-TH updated:
-
-
The syndicate uplink is now complete with a new spooky background. Very neat!
-
-
DoctorDrugs updated:
-
-
Adds additional roundstart miner slots and the additional gear required for them to do their jobs
-
-
Fox McCloud updated:
-
-
Fixes being able to sharpen toy double-bladed energy swords
-
-
IAmBigCoat updated:
-
-
Added explosion warnings to medbeams, because medbeams can cause explosions. DON'T CROSS THE BEAMS!
-
-
Ionward updated:
-
-
Fixed vox jester uniform not appearing correctly.
-
species specific fit underwear for greys
-
-
KasparoVy updated:
-
-
Re-adds the ability to see in the dark. Adds overlays for each level of darksight (>=8,7,6,5,4,3,<=2).
-
-
Kyep updated:
-
-
Round time (h:mm) and station security level (green/red/blue/etc) are now visible on our server hub entry.
-
Round time is now visible to all player-controlled mobs in their status panel (including simple animals).
-
Admins using the 'MOST' attack log setting no longer see player-v-NPC combat, or any attack logs generated in the admin room, admin testing area, thunderdome arena, or lavaland syndicate base. Prevents admins being spammed with attack logs.
-
Heads of department may now issue department-specific medals to members of their department.
-
-
Markolie updated:
-
-
Humans and mice that are secretly blobs now have an antagHUD icon.
-
All hivemind languages now display follow links to ghosts.
-
Announcements, whispers (with ghost ears) and cultist messages are no longer displayed in the lobby.
-
The sentience event no longer triggers a huge number of ghost polling messages.
-
When xenomorphs are damaged, their health HUD now updates properly.
-
Custom title for ghost notifications now work properly.
-
Fixed double admin commands in the grenade priming message.
-
Ghosts will now always see whispers/zero pressure speaking if they're on the screen with the mob speaking.
-
Ghosts with ghost sight enabled will no longer see emotes from clientless mobs.
-
The prison labor point system has been refactored so it works properly.
-
Plating can now be removed (exposing the baseturf) using a welder.
-
All remaining Lavaland ruins have been ported over from /tg/.
-
All chairs on shuttles have been replaced with brand new shuttle chairs.
-
Tribal splints have been added to the game, which can be crafted with two bones and one piece of sinew.
-
The Lavaland Syndicate base now has a defibrillator and mounted defibrillator. The animal hospital now has a mounted defibrillator.
-
The Ash Walker storage area now comes with an advanced medkit instead of a regular one and one set of medical splints. It also comes with aloe vera, comfrey and wheat seeds.
-
The water tank in the Ash Walker nest has been replaced with a puddle.
-
The items in vending machines on the beach ruin and animal hospital are now free.
-
Fixed an issue where slimes wouldn't take damage from water in space.
-
It is no longer possible to unanchor the surivval pod storage units.
-
Drinking from a beaker now only applies the effect of five units of the ingested chemical, instead of the entire volume of the beaker.
-
Resolved an issue where beaker attack logs were reversed.
-
Moving through portals very quickly no longer breaks movement.
-
-
Quantum-M updated:
-
-
New sprites for vampires being "hungry".
-
New sprite for vampire usable blood count.
-
New sprites for the safety muzzle.
-
Safety muzzle (aka the anti-bitting one) can no longer be resisted out of.
-
Vampires can now suck blood from monkey mobs (e.g. monkeys, stoks, etc.) for sustenance but do not get blood power points.
-
RnD is no longer able to print out any telescience boards.
-
-
SteelSlayer updated:
-
-
Gives vampire thralls an objective, which can be viewed in their notes
-
Increases the size of the enthralling message seen by newly created vampire thralls
-
Vampire thralls are now stunned briefly (about 3 seconds) upon being enthralled
-
The AI's robot control window now allows you to see and interact with available bots again
-
-
TDSSS updated:
-
-
cult teleport runes and similar powers now work on z levels 9-12
-
-
Tayyyyyyy updated:
-
-
Inputs sanitized
-
autocomplete input mishandling single quotes (you can teleport to Wizard's den now)
-
newlines not working in CC announcements
-
players not being able to send single quotes in ahelps or PMs
-
robots not being able to pick their name
-
-
TheSardele updated:
-
-
Lowers throwforce of drinking cartons from 15 to 0
-
Bees no longer inject venom when nuzzling
-
Sec pod pilots can now spawn with the loadout security armbands
-
It is no longer possible to raise zero to -infinity fingers using the *signal emote
-
Earmuffs now properly protect you from vampire screeches no matter what you are wearing on your other ear
-
-
Ty-Omaha updated:
-
-
Reworded permanent bans to non-expiring bans.
-
Door remotes now add to admin-only hidden fingerprint list
-
Gave plastic surgery to line 364 of atoms.dm
-
-
and DominikPanic updated:
-
-
Limits IC notes
-
-
datlo updated:
-
-
Free Golems are now a lavaland ruin spawn instead of a space ruin spawn.
-
Free Golems must now purchase their shuttle board for 2000 mining points before being able to fly their shuttle.
-
Added a shuttle recall console at the golem lavaland spawn point so that golems can always recall the shuttle back to lavaland
-
The Free Golem Ship can now move to the Construction Site, the Derelict, or back to their Lavaland spawn.
-
The Free Golem Ship has been redesigned with an open floor plan, removing most of its interior walls for extra space.
-
Free Golems no longer get a free kinetic accelerator on their ship.
-
New crit species with below -100 health will be considered dead for hijack purposes, and will not interrupt a shuttle hijack attempt.
-
Fix some cases of traitors getting conflicting objectives, such as assassinating and protecting the same target.
-
-
farie82 updated:
-
-
Beepsky will now respect your disguise again. No more looking right through that gasmask
-
Medical and security HUDs now use the correct way to identify somebody. They will see the same as you do on your screen.
-
You will now get a job icon in the sec HUD when you use your PDA as ID. It'll use the PDA's assigned job.
-
Ticket takes now ask for confirmation if you want to take an already assigned ticket.
-
Blindfolds are now craftable from 3 cloth. For those vampire prisoners you want to keep in check
-
Empty beaker button from the PANDEMIC is now replaced with Empty and eject beaker
-
List AFK players is now a verb for admins to use
-
Adds the AFK auto cryo system. By default it won't affect players unless they activate it themselves by setting the preference in their game preferences tab.
-
The syndicate can't use meta warfare no more. Advanced pinpointers no longer crash the server
-
-
iantine updated:
-
-
Mouse suicide
-
-
improvedname updated:
-
-
adds lasagna
-
-
kazboo updated:
-
-
changed the display name shown to a player upon being frozen in a manner that only the admins ckey is displayed, not the character name along with it
-
-
-
08 July 2019
-
Arkatos updated:
-
-
Clicking on a health doll icon will now check you for injuries
-
Rechargers now show their contents and charge status on close examine
-
Smartfridge will now try to put an item in your hands after vending, if able
-
-
AzuleUtama updated:
-
-
The cybernetic implant bundle can no longer be bought by traitors.
-
-
Citinited updated:
-
-
Alt-clicking the RPD now brings up a radial menu with rotate, flip, and delete modes accessible. The main interface remains unchanged.
-
Writing in blood can't be done while dead or incapacitated any more
-
You can't write stuff in blood at a distance any more
-
-
Couls updated:
-
-
lantern sprites
-
typo in msg
-
-
Improvedname updated:
-
-
Explorer suits now properly hide tails
-
-
JKnutson101 updated:
-
-
Fixed Construction Permits deleting themselves prematurely.
-
-
Kyep updated:
-
-
fixed a bug with biogenerator.
-
-
Markolie updated:
-
-
Ghosts can now see all PDA messages when enabled through a preference setting.
-
The Mask of Nar'Sie transformation buttons have been removed, as the mask was removed a long time ago.
-
-
Shadeykins updated:
-
-
Changed Quarantine, NT Default, Aggressive, and Corporate AI lawsets. balance: Reduced the ability for NT Default AI's to murder people just because.
-
Removed several redundancies in Aggressive lawset.
-
Fixed a few subject-verb disagreements (is -> are).
-
-
Tayyyyyyy updated:
-
-
paper supports markdown as well as pencode
-
Autocomplete for ghost buttons
-
PMs window scrollable
-
Fix a bug where a player who reconnects is still shown as disconnected
-
-
datlo updated:
-
-
Fix an antag rolling exploit.
-
-
-
30 June 2019
-
Crazylemon64 updated:
-
-
SDQL2 no longer allows a macro argument
-
-
-
28 June 2019
-
AffectedArc07 updated:
-
-
SSticker
-
You can no longer force-start a round unless its fully initialised.
-
Tweaks some preference orders
-
Moved a global define
-
-
Akatos updated:
-
-
Smartfridges now visually show approximate number of items inside
-
-
Arkatos updated:
-
-
Ragin' Mages gamemode should now be playable without any major issue
-
Slaughter and Laughter Demons no longer have duplicit objective shown at the Round End
-
Laughter Demon is now properly called Laughter Demon instead of Slaughter Demon in the role polls
-
Improved wording and fixed mistakes in Wizard and Ragin' Mages gamemodes
-
Wizards are now properly polled in the Ragin' Mages gamemode
-
You can no longer buy Summon Ghosts spell in the Ragin' Mages gamemode
-
You can no longer buy Bind Soul spell in the Ragin' Mages gamemode
-
Deck of tarot cards renamed to Guardian Deck in the Wizard spellbook
-
Rituals and Challenges categories merged into one in the Wizard spellbook
-
Laughter Demon is now slightly weaker compared to the Slaughter Demon
-
Bottle of Ooze now creates a magical morph instead of a normal one. Magical morph is capable of casting smoke and forcewall spells.
-
Visible ghosts will now get a special description about their visibility
-
Removed Cursed Heart from the Wizard spellbook
-
Changeling verbs replaced with action buttons
-
Changeling ability descriptions updated
-
Added custom icons for changeling action buttons
-
Added movement animation for mice, chickens and killer tomatoes
-
Added inhand sprite for eggbox
-
Added inhand sprites for all types of soaps
-
Added inhand sprite for small parcel
-
Added inhand sprite for sechailer
-
Added inhand sprite for bag of holding
-
Added new system for outputting contents of smartfridges
-
Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one
-
Fixed and improved some descriptions regarding Blob offspring
-
Fixed a case where ghosts had an extra ghost icon visible on them
-
Fixed a case where some ghosts were too bright
-
You are now unable to swap forms with another changeling
-
You can no longer hiss while muzzled
-
Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability
-
Changelings in the lesser form can now toggle Augmented Eyesight ability
-
Changelings are now removed properly via Traitor Panel
-
Changelings do not get their action buttons bugged when using Swap Forms ability now
-
Action buttons should update their cooldown statuses more reliably
-
Changelings should now correctly receive their action buttons
-
Changelings now do not steal action buttons from other changelings
-
Added new Boo! spell icon
-
-
Christasmurf updated:
-
-
Fixes a random pixel on the leather shoes
-
-
Citinited updated:
-
-
Boo affects APCs again
-
Boo no longer fully charges when you enter your corpse
-
The button to close radial menus is much more obvious and easily-clickable now
-
Destroying a disposals trunk should no longer occasionally delete things held inside it.
-
Fixes conveyor belts not moving items spawned via an autolathe. (And other possible behaviours when machines switch between speed and normal processes)
-
Ports liquid dispenser sprites from tgstation.
-
-
Couls updated:
-
-
Only names from the manifest will be used for syndicate code phrases
-
randomly generated people names from syndicate code phrases
-
Medical category to exosuit fabricator with implants and cybernetics
-
t-t-t-typo!
-
codephrase names no longer appear blank
-
-
EmanTheAlmighty updated:
-
-
Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult.
-
-
Evankhell561 updated:
-
-
Portable Seed Extractor designon the protolathe.
-
-
Fethas updated:
-
-
Fixes an oversight from the lavaland port invovling Laz injectors and sentience typing that didn't carry over from tg.
-
-
Fox McCloud updated:
-
-
Future proofs the coming Ticker subsystem
-
Removes the Process Scheduler
-
-
Improvedname updated:
-
-
Cargo miner starter kit crate will no longer include a ID
-
-
Kyep updated:
-
-
Ported XKeyScore from TG.
-
New system to securely link ingame/forum accounts
-
Removed old insecure 'link discord account' system
-
unanchored vending machines will no longer generate a runtime error when throwing products at people.
-
Disarming/grabbing a door with IDSCAN disabled no longer results in a can_admin_interact runtime error.
-
Terror Spiders no longer trigger their special attack when nuzzling someone on help intent.
-
-
Markolie updated:
-
-
Chameleon items now use the appropriate species icon.
-
Lighting now respects color blindness again.
-
pAI flashlights now work properly.
-
Rotatium can now be created properly.
-
Ghosts can now transition through space again. This is now done by clicking on the edge of space.
-
Added custom explorer gas mask sprites for Grey/Drask.
-
Added a lantern to the Hermit cave.
-
Added a bone setter, bone gel, FixOVein, sterile masks and sterile gloves to the Lavaland Syndicate base.
-
The pickaxes on the Lavaland labor camp have been replaced with safety variants. The flashlights have been replaced with lanterns.
-
Fixed many species missing sprites for explorer gas masks and jumpsuits. They now use the humans icons until we have custom sprites.
-
Resolved an issue with piping not working on the Lavaland mining bases.
-
Fixed all items being free in the mining vendor.
-
Fixed improper wiring to the turbine in the Lavaland Syndicate base.
-
Fixed the Lavaland Syndicate base oxygen sensor not working.
-
Moved the pipe dispenser in the Lavaland Syndicate base so it doesn't clip with tables.
-
Fixed the Lavaland Syndicate base incinerator doors not working.
-
Ash Walkers now once more have fine manipulation. Their lack of fine manipulation caused unintended side effects (such as them being unable to mine).
-
Ash Walkers (and other ghost spawner roles) can no longer be antagonist targets or become antagonists through the antagonist creation.
-
Fixed the Lavaland Syndicate base incinerator buttons not working.
-
Fixed the Syndicate communication agent spawning with a broken voice changer mask.
-
Fixed the Disk Compartmentalizer not having a sprite.
-
The Ancient Goliath now has a small chance of spawning instead of regular goliaths.
-
Survival capsules now have a NanoMed.
-
Water bottles now behave as glass containers.
-
The behaviour of glass reagent containers has changed. When used on non-mobs, contents will now only be spilled on harm intent. When used on mobs, on any intent aside from harm the contents will be fed to the mob like regular drinks. On harm intent it will still be spilled.
-
Hairless hide can now be made wet using most sources of water (minimum volume of 10), instead of just washing machines.
-
Added some additional offstation role checks to ensure ghost spawner roles don't become antagonists, are kidnap targets or are counted towards station goals.
-
Fixed some piping in the Lavaland Syndicate base incinerator and made sure the vault door starts locked.
-
Fixed the Lavaland swarmers getting stuck on propulsion.
-
Fix goliath tentacles sometimes being left behind.
-
The walls around the Lavaland Syndicate base turbine have been coated, to prevent them from starting a plasma fire in the base.
-
Syndicate agents can now access the air alarms on the Lavaland Syndicate base.
-
Air alarm control computers can no longer access the air alarms on the Lavaland Syndicate base.
-
Fixed the disk compartmentalizer/drying rack missing a sprite under certain circumstances.
-
Fixed the Lavaland Syndicate base triggering atmospherics alerts.
-
You can now properly place tiles on basalt.
-
An exploit with the sheet multiplier has been fixed.
-
Portals can now be activated by clicking on them with or without an object. Ghosts can now also click on them to be taken to their destination.
-
Portals now warn admins when they are used to teleport megafauna.
-
The singularity can now eat basalt and chasms on Lavaland. They get turned into lava.
-
AI swarmers will no longer get stuck on effects (such as blood).
-
Fixed the spectral blade turning all ghosts visible.
-
Fixed a runtime with assigning outfits to mindless mobs.
-
Fixed certain alarms triggering despite being outside of station contact and the Syndicate base still triggering fire alarms.
-
Fixed being unable to put the wormhole jaunter in the belt slot.
-
Fixed the disk compartmentalizer not accepting disks.
-
Gutlunches and Gubbucks will now reproduce properly.
-
The necropolis chest cult clothing drop no longer spawns with a cult hood as well, as that's part of the suit itself.
-
Goliath steaks can now be eaten properly.
-
Fixed a stray light on the beach ruin.
-
Lavaland ruins should no longer spawn on the Labor Camp.
-
Ancient goliaths will now properly randomly spawn tentacles.
-
The labor camp will now spawn properly with a processing console.
-
Water turfs in the beach ruin (and other water turfs that previously didn't do so) will now properly apply water to you.
-
Ash flora is now anchored.
-
Gutlunches will now eat properly.
-
The tesla can no longer travel through wormholes.
-
Fixed an issue with honkbot construction.
-
-
Markolie and Ionward updated:
-
-
Added Tajaran, Vulpkanin, Unathi and Vox sprites for the explorer gas mask (thanks to Ionward!)
-
Added custom species sprites for the explorer suits and hoods (thanks to Ionward!)
-
Added missing surgical tools and a pet vendor to the animal hospital.
-
Added a custom cigarette vendor to the beach biodome ruin.
-
Added an autolathe and RPD to the Lavaland Syndicate base. Also added a custom cigarette vendor and made the vendors not charge money.
-
Added tiny fans to the mining base and labor camp exist.
-
A separate jobban for ghost roles has been added.
-
The alternative sink now has directional sprites. This resolves an issue with shelters having sinks facing the wrong way.
-
Fixed the Syndicate sleepers on the Lavaland Syndicate base pointing the wrong way when a ghost role spawns in.
-
Fixed Lava being removed by the staff of lava not working. Also added a missing warning effect when the staff is turning regular turf into lava.
-
Fixed random bookcases not spawning books (hopefully).
-
Fixed surgical drapes not having a sprite.
-
Fixed being unable to modify the GPS tag of shelters.
-
Fixed the Lavaland swarmers not eating anything.
-
The ash drake swoop attack is no longer incredibly loud.
-
The Syndicate base self-destruct is now much more powerful and capable of destroying the entire base.
-
The flavor text of Ash Walkers and Syndicate operatives now clarifies what they can('t) do.
-
Ash walkers can no longer use machinery.
-
-
Ported by Markolie and CornMyCob. Developed by many /tg/ coders updated:
-
-
The mining asteroid has been replaced with Lavaland.
-
-
Shadeykins updated:
-
-
Fixes a paper exploit.
-
Fixes rogue pixels on breath masks/gas masks for Plasmamen.
-
-
TDSSS updated:
-
-
Vampire rejuv wakes you up if you're asleep now
-
Cling epinephrine wakes you up if you're asleep now
-
Sling glare popup no longer lists invalid targets for glaring
-
-
Tayyyyyyy updated:
-
-
Messages window (My PMs in OOC tab)
-
You no longer have to wait on others for ERT spawning
-
Admin jobs no longer announced
-
-
Terilia updated:
-
-
Added the Donksoft sniper into the Trader spawnpool.
-
-
Ty-Omaha updated:
-
-
Changed admin take ticket color from neon green to Asay pink
-
Manual bans now auto-note
-
Stops projectiles using the legacy system such as emitters from hurting shield blobs due to an exploit where it would always hit or go through.
-
-
craftxbox updated:
-
-
Highlight string uses regex
-
Removed jquery mark
-
-
datlo updated:
-
-
The Syndicate will no longer hire golems as agents.
-
Banana juice and Banana honk will now heal everyone with the Comic Sans mutation instead of checking for the clown job
-
Nothing will now check if the player has an active vow of silence instead of checking for the mime job
-
Ghosts will no longer get the wrong role offered when a nukie spawns a borg and will properly be informed whether they will spawn as a nuke ops or a syndi cyborg.
-
-
dovydas12345 updated:
-
-
Fixes cryopod removing ambulance, secway keys
-
Fixes cryopod recovering the invisible headpocket item
-
-
farie82 updated:
-
-
Can't use cuffs now while you have antidrop
-
can_equip now checks if you have the limbs required to equip something
-
Reverts the string highlighting done by regex
-
-
iantine updated:
-
-
Skrell *warble emote
-
-
uc_guy updated:
-
-
Theft objective locations hints now ignore the Centcomm Z level.
-
Adv. Pinpointer no longer targets items in Centcom Z level.
-
Fixed "Venus Human Traps" being invisible.
-
-
-
10 May 2019
-
AffectedArc07 updated:
-
-
Removes an infinite loop in the code
-
Removes unused code
-
Captains display case now actually has captains thumbprint lock on it
-
Morgue updates happen slightly better now
-
Fixes a minor NTTC issue
-
-
Arkatos updated:
-
-
Patch Pack is now craftable with a cardboard, costs 2 cardboard sheets.
-
Examine tooltip delay increased slightly
-
Examine tooltips now work properly on items in storage
-
Full toolbelts now spawn with randomly a colored cable coil
-
Added inhand sprites for belts
-
Species name now shows in a species theme color on examine
-
Added 4 new plushies
-
-
Couls updated:
-
-
necromantic stone now forces the ghost back into the body as a skeleton
-
allow skeletons to give up their bodies and offer control to ghosts
-
-
Crazylemon and Fox McCloud updated:
-
-
Fixes toggles not properly saving
-
-
EvadableMoxie updated:
-
-
Added the Nanotrasen Hospital Vessel Asclepius, able to be deployed by admins.
-
Admin shuttle now requires ERT clearance instead of admin clearance.
-
Admin shuttle now has a navigation computer and tiny fans at the airlock.
-
-
Fox McCloud updated:
-
-
Fixes a few instances generating log spam relating to z-level tracking
-
Fixes weird behavior with ghosts being able to trigger a few things by crossing over them
-
Fixes drifting ghosts
-
-
Ionward updated:
-
-
Updated the cautery sprite!
-
-
KasparoVy updated:
-
-
Adds a verb to eyewear you can use to adjust them so they appear above or below masks. Discover interesting combinations and enjoy a cool look.
-
-
Kyep updated:
-
-
Trying to latejoin a round with no open job slots now results in an informative error message, rather than broken-looking blank window.
-
Added new bonus loadout items for higher-tier patrons. Also gave admins access to patron items, and ensured that during custom events, you see the custom event announcement when you connect.
-
You can now identify when someone is using internals from a tank in their pocket, without having to remove the tank.
-
punching a windoor no longer generates a runtime error.
-
cryogenic_liquid/envenomed_filaments blobs no longer generate runtimes when their blob special attack hits mobs that do not process reagents
-
fixed $5+ donors not getting extra loadout points.
-
-
Markolie updated:
-
-
Ambient occlusion had been added to the game. This represents a shadowy effect on most objects. It can be turned off through the game preferences menu.
-
Our lighting system has been updated to /tg/'s latest version. Hopefully this means we'll have less lag later in the round.
-
Night vision has been modified. There are now three levels of night vision. Certain creatures that were previously able to toggle night vision can now switch between all levels. Thermals now give some night vision.
-
Mesons now no longer fully light up non-visible turfs. It uses slight darkness instead.
-
Syndicate operatives may now purchase a chameleon bundles (2TC), which allows them to disguise not just their jumpsuit, but all of their equipment. They can change individual clothing as well as the outfit as a whole.
-
When using a voice changer, NTTC will no longer default to an "Unknown" job: it'll still use the assignment on your card to prevent meta-gaming. Always combine a voice changer and a Syndicate ID.
-
Admins with advanced admin interaction toggled on can now interact with the small airlock buttons.
-
The steel_rain runtime fix has been re-applied.
-
The propulsion on the admin shuttles has been fixed. The shutters on the south side of the hospital shuttle now point the right way.
-
Nuclear Operative reinforcements now spawn with a properly counted agent designation.
-
Fixed an issue where a mob's sight wouldn't update properly in certain cases, such as being revived.
-
Resolved an issue where the lobby would be bright white when being sent back.
-
Resolved an issue where the ambient occlusion preference wouldn't update properly in the lobby.
-
Resolved an issue where clicking on a windoor would no longer prevent it from auto-closing.
-
When a nuclear operative chooses to play as the borg instead of operative using the cyborg teleporter, ghosts will now be informed of this in their acceptance message.
-
Resolved an issue where cameras couldn't take pictures of non-dynamic lighting areas, such as the holodeck or space.
-
Resolved an issue where mobs would appear above water.
-
Resolved an issue where radiation storms would make lighting invisible in space.
-
Simple mobs no longer retain their X-Ray upon being revived.
-
Applying brute/fire damage through the View Variables menu for non-humans has been fixed.
-
NTTC regex has been disabled due to an urgent security issue.
-
-
Mitchs98 updated:
-
-
You can now order a Pig Crate from Cargo for 25 points.
-
-
TDSSS updated:
-
-
typo on sst shuttle console
-
opening turret covers now stay on top of their turret.
-
-
Twinmold93 updated:
-
-
Adds Server Time to the Status Tab for Admins.
-
-
farie82 updated:
-
-
Transforming into another species will now retain the items correctly. Example clings will keep their armblades and they won't get stuck with a non existing armblade they can't put back
-
Devour and regurgitate use forcemove now. So no being buckled inside an alien
-
-
fludd12 updated:
-
-
Project Mind now has a corollary ability, Scan Mind. Now communication can be two-way!
-
-
variableundefined updated:
-
-
Simple animals actually use the new subsystem now
-
What was NPCAI is now renamed to NPCPool - Its the functional equivalent of what it is in tg
-
Simple animals actually run on subsystem instead of a process now.
-
idleNPCpool has been added reducing performance impact of hostile simple animals
-
NPCAI Process (That run both SNPC and SimpleAnimals) that was somehow left out by me
-
SNPC & assocaited NPCAI Subsystem
-
Some of space hotel's functions.
-
Bodysnatch gland.
-
process_ai has been deprecated
-
-
-
02 May 2019
-
AffectedArc07 updated:
-
-
ssMapping
-
Gateway and space ruins are now loaded with ssMapping
-
Master Controller
-
Darkmode chat department colors match NTTC theming now
-
SSvotes
-
SSradio
-
SSevents
-
SSholiday
-
We no longer check if its Christmas every tick. Dont ask.
-
SSalarms
-
-
Arkatos updated:
-
-
Shadowlings now have a slightly bigger colored text when speaking in the Shadowling Hivemind
-
Replaced title2.ogg music with a higher quality version
-
Shield Blobs automatically spawned around Blob Cores now give no refund upon removing. No freebies.
-
Added new Wizard Spell - Summon Ghosts! This nefarious spell will make all ghosts visible to the living. Be careful though, as while they cannot harm you in any way, they might prove a bit.. annoying. Costs 0 points in the Wizard's spellbook.
-
Ghosts now orbit around their followed targets
-
Added new Shadowling Ability - Null Charge! This new ability allows Shadowling to completely drain an APC of it's power after a moderate delay. Shadowling must not be interrupted, or the whole process will fail.
-
Added custom icon for the Null Charge ability
-
Shadowling Drain Life ability removed
-
Added Observer HUD buttons for Jump to Mob, Orbit, Re-enter corpse, and Teleport
-
Added custom icons for Observer HUD buttons
-
Added Floorbot color variants. Different toolboxes will result in a differently colored Floorbots. One even might be a little stronger than others..
-
Added sprites of Floorbot color variants
-
Fixed incorrect amount of required floortiles for the Floorbot in the crafting tab
-
Added cancel button to Wizard teleportation scrolls
-
Added an option to grant Martial Arts via administrative Var menu
-
Toggling hardhat light on/off now correctly updates wearer's sprite
-
Added deathsound for Silicons
-
Dice will now roll when thrown
-
Added sound when adding or removing IDs from ID modification computers
-
Added cancel button to transfer amount from stack menu
-
Alt-click is a new shortcut to take a custom amount from stack
-
Added shortcuts for handling pumps, volume pumps, filters, and mixers. Ctrl-click these devices to turn them on/off and Alt-click them to set their output to maximum.
-
Added ability to rename pumps, volume pumps, filters and mixers with a pen.
-
Added sound for throwing bolas
-
Added hitsound for all types of bolas
-
Added AntagHUD to everyone at the round end
-
Circuit Boards now show their required components on examine
-
Revenants now have randomly generated flavor names
-
You can shift-click any action button to reset it's position. Alt-click on Hide Buttons will reset all action buttons to their default positions.
-
Pill Bottles are now printable in the Autolathe. You can find them in the Medical section, and each costs 80 metal and 20 glass to print.
-
Puts beakers in your hand upon eject from chemistry machines
-
Cardboard can now be made in the Biogenerator
-
You can now hotswap tanks in a canister or gas pump by clicking it with a new tank!
-
You can now also close a canister's valve and remove the tank inside it by alt-clicking it.
-
Added examine toolptips. Hover over any equipped or hold item for a little while and it will display the item description as a tooltip.
-
Ghost teleport verb will no locker flicker when used
-
Alt-click now opens and closes fire extinguisher cabinet
-
Fire extinguisher cabinet now properly updates it's sprite correctly when putting fire extinquisher inside the cabinet
-
Fire extinguisher no longer sprays when put into fire extinguisher cabinet with a safety off
-
Added sound for opening and closing fire extinguisher cabinet
-
Added new torch sprites
-
Torch light color is now orange instead of red
-
Torch sprite now correctly shows all inhand sprites
-
Blob Rally Spores power is now free to use
-
Blob mobs can no longer speak while being dead via Blob Broadcast
-
Blob structures now properly show working animation
-
Added new sprites for variants of Blob resource, factory and storage structures
-
Added inhand sprites for winter coats
-
Carps now spawn with a random color! There might even be some really rare ones..
-
Added carp color variants sprites
-
-
Arkatos and Paradise community: updated:
-
-
Added Tip of the round to a pre-game lobby
-
Added Show Custom Tip admin verb
-
Added Give Random Tip OOC verb
-
-
Citinited updated:
-
-
You can no longer turn transit turfs into foamed metal flooring.
-
Foamed metal floors have a sprite now.
-
Pipe dispensers (the big ones) now work again.
-
Cooldown on pipe dispensers reduced to 0.4 seconds, down from 1.5 seconds
-
-
CornMyCob updated:
-
-
The plasma cutter now cuts through multiple rock tiles.
-
-
CthulhuOnIce updated:
-
-
you can smell dead bodies, even if someone else shouldn't
-
-
Fethas updated:
-
-
Cluwne suits should no longer fall off cluwnes from being fat.
-
-
Fox McCloud updated:
-
-
CQC has been updated; a few combos are more powerful
-
cost increased to 13 TC
-
CQC is now nuke ops only
-
gloves of the north star restriction on CQC removed
-
CQC disarms will now take the item from your opponent
-
CQC blocks melee weapons and a couple of stun weapons and not everything now
-
Reagents will now adjust to the body temperature over time as opposed to all at once
-
Strange Reagent will work 25% of the time with TOUCH based reactions
-
Strange reagent will revive whether there's a ghost or not (can use SR on clientless mobs now, like monkies)
-
SR puts the occupant back in their body automatically
-
Cloners that eject their messes will now eject the unattached organs
-
the message for brain death will now properly and only occur when they have truly died from brain damage
-
Fixes being able to attain brain damage over 120
-
Updates nations. Updates nations so hard right into the void
-
Plasma fires should burn a bit faster now
-
Bleeding will now stop at the temperature at which cryoxadone heals
-
Fixes a few potential exploits with forcing chem, dust, and explosive implants activating with the deathgasp emote, prior to death
-
Tesla can't zap cameras and other disposal structures anymore
-
Simple mobs can now be shocked
-
Electrocution damage scales a bit more linearly up to its maximum potential instead of being heavily random
-
Fixes being able to shock yourself with TK, at range, on electrical equipment
-
simple mobs can now be shocked by the tesla and other sources
-
Fixes goats not attacking people
-
Goats will eat glowshrooms
-
Goats will eat full grown diona
-
Remapped toxins to be more compatible with the modern age
-
updates plasma and N2O sprites
-
Fixes not being able to look at a turf if it had plasma/N2O on it
-
cold turfs no longer become icy
-
Cryostylane makes turfs icy
-
Icy turfs are slippery; wear magboots to counteract the effect. Watch your head!
-
Fixes grammar of slipping on turfs; no more "you slipped on floor" or "you slipped on wet floor"
-
removes ponies
-
object and fast processing are now proper subsystems
-
Fixes multi-spawn blobs
-
Powersinks drain rate increased, but they also explode a bit sooner
-
Multitools display total power, load, and free power
-
Fix emitter sparks sparking at the location of emitters where biult as opposed to emitter current location
-
-
Ionward updated:
-
-
Added new mantles! Check the ClothesMate, or in department head's lockers.
-
-
KasparoVy updated:
-
-
Adds striped normal-height socks.
-
Vox can now wear whatever undergarment they want.
-
Removes flesh from shredded Vox uniform sprites.
-
Armalis can no longer wear undergarments. They didn't fit, anyhow.
-
Underwear no can no longer lock up the character creator.
-
-
Kyep updated:
-
-
bans issued by admins via the Player Panel no longer incorrectly omit IP/etc information
-
admins issuing permanent bans are no longer presented with an "ip ban?" prompt, as all bans include IP/CID information now. This prompt was a legacy thing from back when the filesystem was used to store bans, and hasn't ever affected how DB-based bans were stored.
-
Added a config file option which allows SSD crew members to be moved to cryo after a defined amount of minutes.
-
Added a config file option which causes most people trying to attack/loot/interact with a SSD character to need to confirm they've read the rules before being able to do so.
-
Fixed an error message being inappropriately generated for admins when someone signs up as a pAI.
-
The ID computer now color-codes potential job transfer options, highlighting good choices for a job transfer in green, and bad ones in gray.
-
Taking a job transfer now gives you playtime based on your new job, instead of incorrectly still giving you playtime based on your old job.
-
Job transfers to karma jobs are now possible - if you have the job unlocked.
-
Attempting to bypass a job ban via a job transfer now generates a warning to all online admins.
-
Refactored and improved our entry on the server hub.
-
Fixed a runtime in job_exp.dm
-
-
Markolie updated:
-
-
Safes can now consist of more than two tumblers.
-
All safes now have three tumblers by default, instead of two.
-
The safe opening mechanism has changed slightly. This is described on the safe cracking UI.
-
The hardsuit equipment lockers on the Syndicate Nuclear Operative shuttle have been replaced with suit storage units. Suit storage units now have a separate slot for magboots.
-
Nuclear Operatives can now purchase reinforcements. These reinforcements cost 25 telecrystals each.
-
A number of new ammunition and weapon bundles have been added for Nuclear Operatives.
-
For every ten players on the server, the Nuclear Operatives now receive 2 extra telecrystals.
-
The Syndicate borg spawners have been separated into three separate spawners, one for each type of Syndicate cyborg. Their prices have been modified.
-
Saboteur borgs now spawn with thermals.
-
The Syndicate borg and exosuits have been moved to a new category, "Support and Mechanized Exosuits".
-
Existing bundles and telecrystal purchases have been moved to a new category, "Bundles and Telecrystals".
-
There are now more spawn points for nuclear operatives on their base. The number of operatives spawning has not been changed.
-
Spawning nuclear operatives through the traitor panel now causes their ID to be properly updated.
-
Shuttles no longer leave behind their propulsion.
-
AZERTY hotkey mode users can now switch between regular mode and hotkey mode properly using TAB again.
-
Jumpsuits are now removed by clicking instead of clicking and dragging.
-
Removed a useless message that would be sent to admins whenever a drone joins the round.
-
Fixed an issue where admins would receive a message whenever someone joined up as a pAI.
-
-
McDonald072 updated:
-
-
You can no longer examine or teleport things using clipboards
-
-
Quantum-M updated:
-
-
Two multicolor pens to the Internal Affairs Office
-
-
TDSSS updated:
-
-
nukies can buy plasma grenades again
-
-
Ty-Omaha updated:
-
-
Moves AI admin log to the all preference
-
-
dovydas12345 updated:
-
-
Fixes normal cameras spooking non-chaplains even when they don't capture any ghosts
-
-
farie82 updated:
-
-
Makes puke less lag inducing
-
Puke can now appear on all kinds of turfs except spess
-
Ticket messages now have their corresponding span classes. Making them easier to notice
-
PM's now shouldn't go to the wrong client anymore when the target left.
-
Cure text for Shock and Cardiac failure are more clear now
-
Ducttape gags can now be removed properly without spawning an invisible one in your hands
-
Windoors now give the airlock assembly electronics once deconstructed
-
Can't place runes in space anymore
-
Admins can now use all mhelp related things again
-
Fixed the toggle mentor ticket messages text
-
Vampiric glaring is logged now
-
Doctor delight and orange juice now heal again
-
Fixes admin PM's. Bwoinks are back on the menu!
-
Organs will now prompt a update_stat. Meaning that IRCs and the like now get revived when possible when you put their battery and brain in
-
The typing limiter option should now work for all edge cases. Such as dying while talking and such
-
Borgs health status now updates properly when removing and adding parts
-
You won't try to fix destroyed components in borgs anymore. Which resulted to lost materials and no healing
-
Borg analysers will now properly show missing components and won't show their damage if missing
-
Self diagnostics for borgs now also shows missing parts and destroyed ones
-
-
iantine updated:
-
-
Adds Lumi's vox suit fluff
-
-
uc_guy updated:
-
-
Players in the lobby no longer see cult speak.
-
-
-
08 April 2019
-
TDSSS updated:
-
-
Added missing vent in toxins mixing
-
-
-
07 April 2019
-
Arkatos updated:
-
-
Guardians can no longer change action intents on their own
-
Fixes #10900 - Guardians can no longer attack their host while inside them
-
Explosive and Support Guardians now get precise cooldown shown (instead of just static estimate) before their bomb and beacon abitilites are ready to be used again, respectively
-
HARM action intent icon for Guardians updated
-
Dehydrated Space Carp TC cost changed from 3 to 2
-
Shadowling Glare ability reworked - The further Shadowling is from their glared target, the shorter stun their target gets. Stuns also have a delay before they kick in, based on the distance, however targets will be slowed and muted before stun takes effect. Targets on the tile just next to them are still stunned and muted for 10 seconds without any delay.
-
Added victory message to the End Round messages in the Shadowlings Rounds
-
Shadowling Destroy Engines ability reworked. You now need to sacrifice non-ally target to delay the emergency shuttle arrival by 10 minutes, and shuttle will be unable to be recalled. This ability can be used only once across ALL Shadowlings.
-
Descriptions now show with a mouse hover over action buttons
-
-
Fox McCloud updated:
-
-
Fixes Russian revolvers triggering no matter where you clicked
-
Power gloves electric shocks can target anything now (still only damages mobs)
-
Power gloves electric arcs will bounce around (if it happens to target a mob though, it'll ground out and not bounce any more)
-
Power gloves cooldown lowered from 12 to 4
-
Power gloves heat up the turf they target
-
Using power gloves on disarm intent will weaken your target instead of dealing damage
-
CLF3, Phlogiston, and Fluorosulfuric acid all require greater volumes to achieve their upper damage limits
-
CLF3 and Phlogiston have lower minimum damage
-
Grey's treat water more closely to sulfuric acid (including passive damage while it's in them)
-
Grey's don't instantly purge all sulfuric acid from their system; it depletes at the normal rate, but doens't cause damage
-
Foam altered to be a bit more viable compared to smoke
-
Fixes being unable to view pill bottle inventory in some circumstances
-
Vending items from vending machines will try to put the item in your hands after vending
-
Vending machines with refill-canisters can be beaten apart and broken
-
-
Kyep updated:
-
-
Ghosting while alive, conscious, and a member of the crew will now result in your body being moved to cryo after 5 minutes, assuming your body isn't killed or restrained in any way in the meantime.
-
An AI that ghosts while alive gets a dismissable hint that they might consider using OOC -> Wipe Core instead.
-
Ghosting out of your body while you are alive, and an antag, will result in admins being informed, so that they may replace you as an antag if needed.
-
Empress of terror (admin-only mob) is no longer incorrectly prevented from laying brown spider eggs.
-
Admins are now able to spawn a queen of terror in a room without a vent. Previously, queens would not allow this. Now, this just results in an alert to admins (since its probably a mistake) and deactivates the mob AI (but leaves it available for player control).
-
If there are player controlled terror spiders, admins using check antags panel will now be able to see eggs/spiderlings currently growing on the station. These counters only count eggs/spiderlings on station, and ignore fake spiderlings.
-
Empress of terror's 'erase brood' ability no longer incorrectly causes mothers of terror to spawn spiderlings on death. sprite: Empress of terror now has its own sprite.
-
White spider infections have been nerfed a bit. They no longer provide passive healing or increase infection progress while their host/victim is in crit. Also, the first spiderling to emerge from an infection can no longer be a green. Finally, the eggs now self-delete after the third spiderling emerges, so even in the event they aren't treated with surgery, the host isn't left with confused movement forever.
-
-
Markolie updated:
-
-
Changing your hotkey mode now happens instantaneously and no longer lags.
-
An issue where the Hotkey Toggle button wasn't working has been fixed.
-
-
TDSSS updated:
-
-
upload consoles now tell you if you forgot to select an ai/borg before using an upload module.
-
trick revolver comes in a box, so you can tell what it is when getting it in a surplus crate.
-
-
farie82 updated:
-
-
Gives you the option to disable text popup spam. Aka if enabled you won't get popups after you pressed T and had a lagspike and you typed a sentence containing a lot of T's. Default is off
-
Now checks if OOC and LOOC are enabled before showing the popup
-
Adds a Mhelp ticket system
-
Take in the m/a-helps now actually takes the question
-
a/m-help followup responses using a-mhelp verb now get added to the last ticket like it should
-
Normal players can now see their open tickets using the My Admin/Mentor tickets verb
-
-
-
06 April 2019
-
Fox McCloud updated:
-
-
Fixes people popping out of cloning taking tons of damage
-
Fixes Teslium recipe
-
Fixes some reagents not causing status updates
-
-
Twinmold updated:
-
-
No longer costs toner to send a fax to Central Command
-
-
dovydas12345 updated:
-
-
Fixed diamond statue names and description.
-
-
farie82 updated:
-
-
Sec huds work again. No longer does the perp need glasses to be set to arrest. Cool does not equal arrest now
-
-
-
04 April 2019
-
Kyep updated:
-
-
Improved the interface for Syndicate Uplinks. They now clearly mark which items are hijack-only and which are not. If you attempt to purchase a hijack-only item without hijack, they will explain why you can't.
-
Atmos Gas Grenades (the uplink grenade kit) are now split into Knockout grenades (2 N2O grenades, 8 TC, available to all agents), and Plasma Fire grenades (2 plasma fire grenades, 12 TC, only available if you have hijack). This both makes knockout grenades more useful for normal traitors, and also prevents non-hijackers using a plasma fire grenade to cause massive casualties/damage.
-
Plasma Grenades and the Syndicate Bomb can no longer show up in surplus crates, or be discounted. This means while you can buy one if you intend to, you're not randomly encouraged to bomb your target.
-
-
-
03 April 2019
-
Fox McCloud updated:
-
-
Dramatically improves human life performance (sorry, doesn't fix your actual crappy real life)
-
Blobspores will additionally zomify all players who have 200 damage or more
-
Holoparasites will additionally die once their host has 200 damage or more
-
Fixes blob zombies who infect players who have no head being invisible
-
-
farie82 updated:
-
-
Death nettle can be picked up again
-
Auto cloning now doesn't clone a person more than once.
-
A person in the cloning scanner won't be scanned if he's already being cloned
-
-
-
02 April 2019
-
Alonefromhell & AffectedArc07 updated:
-
-
Fixed an edgecase compile error for spacehotel.dmm
-
-
Arkatos updated:
-
-
Added Medical Beamgun to a Syndicate Medical Cyborg
-
Appropriate antagonist sound theme now plays when an antagonist is selected via Traitor Panel
-
Cult sound theme now plays for a new cult converts
-
Traitor/Malfunction sound theme now plays for newly autotraitored crew/AI
-
-
AzuleUtama updated:
-
-
Cleaned up some outdated code left in uplinks.dm
-
-
Fox McCloud updated:
-
-
Fixes some mobs not being able to hear sounds
-
Fixes the Master Controller not actually shutting down on round end
-
Adds space ants to the game; leave your food on tables or inside a container to avoid infestation!
-
Fixes bees not properly generating if they have a reagent in them
-
Can break bee boxes
-
Fixes bees breaking things they shouldn't
-
Fixes bees not properly injecting toxin if they lacked a reagent
-
purchased bee boxes are no longer wrenched down by default
-
Adds trick revolver to the syndicate uplink for the clown. Teach those pesky validhunters a lesson!
-
Adds the ability for admins to start a revolver only summon gun version; there's also a suicidal version that makes half the guns summoned real and the other half trick revolvers
-
stabilizing agent gets used up in reactions that utilize it
-
flashbangs spark when they initially go off
-
Fixes mech users being stunned by their own flashbangs
-
Fixes necromantic stone not working properly and other edge cases where you had O2 damage and could become O2 damage immune
-
-
KasparoVy updated:
-
-
Adds Vox-fitted Tajaran veil sprites.
-
Removed stray pixel from Vox-fitted gasmask sprites.
-
Adjusts the Vox-fitted blindfold sprite.
-
-
Kyep updated:
-
-
Blob mobs can definitely no longer be spawned in xenobio.
-
Changed playtime requirements for command jobs. HoS/RD/CE/CMO/AI now require 5h played in their department to be playable. HoP/Captain now require 5h played as a member of the command staff.
-
-
Markolie updated:
-
-
Fixed some issues the compiler doesn't spot and some start up issues.
-
-
Ty-Omaha updated:
-
-
Start now confirmation is now a config option
-
Grid check event sound effect
-
-
farie82 updated:
-
-
Antidrop give edge case fixed
-
Can't give items to resting people now
-
put_in_hands now checks if you actually have hands
-
Wrapping lockers and crates now takes 1.5 seconds to do
-
Welding lockers now takes 1.5 seconds to do
-
-
-
01 April 2019
-
Arkatos updated:
-
-
New Blob UI buttons for Storage Blob and Split consciousness abilities
-
New custom icons for Storage Blob and Split consciousness abilities
-
Added Node Requirement verb to the Blob. This verb, which is activated by default, enforces that resource and factory blob structures are built in a close proximity of the core/node in order to properly function. Players can disable it anytime in the Blob tab.
-
Remove Blob verb now has a new feature - partial refund for special Blob structures. When Blob Overmind removes special blob structure (such as a factory or node), it will receive 30% of the structure cost back as a refund.
-
Blob Overminds now show in Check Antagonists admin verb
-
Blob Mobs now use complementary colors of the Blob Overmind reagent as their own color
-
Removed Dark Matter from a list of possible Blob reagents
-
-
Fox McCloud updated:
-
-
Fixes syndicate medborgs and regular medborgs not having handheld defibs
-
Fixes multi-tile airlocks breaking and not leaving behind an assembly
-
Updates the Timer SS
-
Roundstart ChemMasters are now constructable/deconstructable
-
Can upgrade ChemMasters. Larger beakers mean a larger reservoir
-
Mobs that are gibbed with strange reagent and GBS have a bit more of a dramatic flare to them with violent convulsions before exploding into tiny bits
-
-
Ty-Omaha updated:
-
-
Modified alert sounds for Code Gamma and Code Epsilon.
-
-
dovydas12345 updated:
-
-
Fixes AI's toggle floor bolts ability
-
-
farie82 updated:
-
-
Bluespace golems no longer can crash the server
-
Spontaneous combustion now has a minimum stacksize of 1. No more getting wet from the fire virus
-
-
-
30 March 2019
-
Fox McCloud updated:
-
-
Fixes a runtime involving decapitation
-
playing sounds performs better
-
-
Ty-Omaha updated:
-
-
Removes SSD sleep bubbles from ghosts
-
-
-
29 March 2019
-
Arkatos updated:
-
-
Fixes #11087 - Swarmers are now locked to their default action intent
-
Swarmers are now able to open airlocks and windoors (access restrictions still apply)
-
Added new Wizard item - Bottle of Ooze! This powerful item awakens all-consuming Morph, ready to eat everyone and everything on the station! Be careful though, as Morph diet also includes Wizards.. Costs 1 point in the spellbook.
-
Added custom icon for Bottle of Ooze
-
Morph introduction is now properly formatted
-
Added new Blob UI and icons, ported from /tg/station13
-
Added new *Blob Help* verb, designated to help out new players playing as Blob
-
Added descriptions for each Blob reagent
-
Added complementary colors for each Blob reagent
-
Blob marker now uses complementary color of Blob reagent as it's own color
Crit has been dramatically overhauled. Treating patients now requires a broader range of medicine. Recommend checking out a guide for how to treat using the new system!
-
Medical vendors now have styptic and silver sulfadiazine, saline, atropine, mannitol, mutadone, calomel, diphenhydramine, oculine, insulin, morphine, and potassium iodide for helping treat new patients. Amount of Gauze, Advanced Trauma, and Burn packs has also been increased.
-
Adds new handheld defibs. Utilize these for treating patients with cardiac arrest. Note: these do not revive people from the dead!
-
Doctors lockers now have a handheld defib in addition to a regular defib.
-
Medical borgs now have a handheld defib
-
CPR dramatically buffed. Heavily lowers O2 damage and resets losebreath to 0
-
Cryoxadone tuned down a little
-
Health analyzer UI altered ever so slightly for cardiac arerest, so it's easier to find
Upgraded Robotic Hearts now attempt to correct both cardiac failure and cardiac arrest tweak; Upgraded Robotic Hearts now do not punish you quite as severely for receiving a shock while having one (EMPs will still destroy you though)
-
Corazone recipe removed
-
hotspot sprites updated; fire will also now appear over top of things, rather than underneath it
-
Roundstart chem dispensers are now construcable/deconstrucable and can be moved
-
Energy ratio for chem dispensers increased by x10 (how many reagents you can dispense before running out and how quickly it recharges is all the same, however)
-
Adds the ability to add a single unit of reagent in the chem dispenser
-
Adds the ability to isolate reagents in the chem dispenser
-
Portable chem dispenser removed (the circuit board for them now makes full dispensers)
-
Fixes some suicides dealing damage and gibbing you at the same time
-
Allows you to suicide with more object types. Currently the only new object type you can suicide with is the gibber
-
-
Kyep updated:
-
-
Blob mobs can no longer be spawned in xenobio.
-
Blob mobs spawned by blob cores can no longer have sentience potions used on them, which would allow whoever controls them to kill the blob with no countermeasure.
-
-
Mitchs98 updated:
-
-
Adds in Shrimp & Fish Skewers as well as Cheeseburgers. Shrimp Skewer(Grill): 4 Shrimp(uncooked) + 1 Metal Rod, Fish Skewer(Grill): 2 Salmon Meat + Metal Rod + 10u Flour, Cheese Burger(Microwave): Burger + Cheese Wedge.
-
-
farie82 updated:
-
-
Borgs can now only cuff people with two hands. Just like humanoids
-
You can cuff people with at least one hand now
-
-
ingles98 updated:
-
-
Plasma Golems will now report their suicide acts to the Admins.
-
-
-
25 March 2019
-
Fox McCloud updated:
-
-
Fixes some reagent performance edges cases
-
Fixes chem smoke lagging under some circumstances
-
Fixes smoke not wanting to garbage collect
-
Fixes flares not returning a qdel hint
-
Fixes hotspots being slow to ignite turfs around them
-
Fixes LINDA not conducting temperature through things.
-
-
Mitchs98 updated:
-
-
Chitinous Mass is no longer weaponized lag if examined.
-
-
farie82 updated:
-
-
Diona nymphs are grabbable and punchable again
-
-
-
24 March 2019
-
AffectedArc07 updated:
-
-
Preferences are now in alphabetical order
-
-
AzuleUtama updated:
-
-
Added Syndicate MMI for Roboticist Traitors, priced at 2TC. balance: Removed Syndicate MMI from the traitor surgery duffelbag. Price reduced to 2TC.
-
-
EmanTheAlmighty updated:
-
-
Can no longer offer Gateway Terror Spiders sentience potions. ( They literally exploded if you did, and that could have been used to effortlessly clear out hordes of them. )
-
Using the Shadowling ability "Hatch" as a monkey will change your HUD to be the human one.
-
It is now possible to put a collar on any animal that has gained sentience.
-
-
Fox McCloud updated:
-
-
Pills maximum size increased from 50 to 100
-
Chem Master bottle size increased from 30 to 50
-
Pill bottles can now hold 50 pills instead of 14
-
Pill bottles can no longer hold patches
-
Adds Patch Boxes, which can hold patches, but not pills
-
Can now use a pill bottle or patch box on someone to apply a pill/patch from the bottle/box to a mob. Usual delays will still apply
-
Can down an entire pill bottle at once!
-
Cryostylane and pyrosium reactions now consume 2 of themselves when exposed to oxygen
-
fires, temperature, and hotspots can heat anything that contains reagents
-
Having hot/cold chemicals dumped on you or ingesting them will hurt you. Wear a mask or hat to protect from having someone dump the hot/cold things on you.
-
Chem Heater temperature adjustment tweaked; can no longer set temperature on empty containers.
-
Chem Heater generally heats faster, but cannot be upgraded
-
Chem Heater automatically stops around target temperature
-
Adjusts fire stacks and how they're applied with a few chems. Naplam, Phlogiston, fuel, thermite, and a few others have all received changes. Most direct fire damage removed.
-
Adds phlogiston dust; a safer, cooler burning Phlogiston.
-
Water and Firefighting foam will no longer automagically put out mob based fires; they'll reduce fire stacks (when fire stacks hit 0 they put the mob out)
-
cryostylane puts out mobs instantly
-
Heating fuel can set it off. Be careful when heating it now
-
Increased welding fuel tank size from 1000 to 4000 (wall mounted are still 1000)
-
Sorium and Dark matter now actually throw things
-
Thermite now gets applied to turfs. You'll have to heat the turf up to ignite it. Anything that can heat can now ignite thermite on walls
-
Adds fake hotspots. They don't do anything except set you on fire when you cross into them. Chemistry's pyrotechnics use these, for the most part; anything that causes a fireball that's chemistry related uses these
-
Sorium and Liquid dark matter now have visual effects
-
Fixes chem smoke being on the wrong layer.
-
Adds in unidentified tank filled with an unknown experimental gas in deep space. Find it and experiment!
-
-
Tails2091 updated:
-
-
New emotes to Cats and Corgis.
-
Change directories for some creature sounds to be in the creature sound folder.
-
Two bark sounds, a yelp, and a meow.
-
-
farie82 updated:
-
-
Holo firedoors now update atmos correctly after being destroyed
-
Inflatable walls/doors now update atmos correctly after being destroyed
-
Alien resin walls now update atmos correctly after being destroyed
-
Foamed metal walls now update atmos correctly after being destroyed
-
Pod doors (shouldn't ever happen) now update atmos correctly after being destroyed
-
Mining flaps now update atmos correctly after being destroyed
-
-
-
23 March 2019
-
Arkatos updated:
-
-
Players who enable AntagHUD are now unable to join the round as swarmers
-
Adds a message explaining why Antag-banned players cannot join the round as cortical borer
-
-
Calecute updated:
-
-
South Prison camera now belongs to Prison camera network, thus showind in Prison camera monitor
-
-
Kyep updated:
-
-
Admins offering control of a mob with no real_name to ghosts will no longer cause a "Do you want to play as ?" popup. Instead, the ? will be replaced with a descriptive string, such as "the blobbernaut".
-
-
Tails2091 updated:
-
-
Lockboxes actually close when locked now.
-
-
farie82 updated:
-
-
When disarming a bomb from a guardian you now don't pickup an empty object.
-
no more organ: spam sorry admins
-
-
-
22 March 2019
-
Arkatos updated:
-
-
Updated Tarot Deck description in Wizard's spellbook, credits to /tg/station13
-
-
Fox McCloud updated:
-
-
Smoke now has much better sprites and has a new area of denial behavior
-
-
Mitchs98 updated:
-
-
Fixed Dionae names so "Embrace of Starsong (as Embrace Of Starsong)" will no longer happen when renaming ID's at a ID Console.
-
-
Quantum-M updated:
-
-
Vox Cargo Crate - Contains two vox tanks and two vox masks. Costs 50 cargo points.
-
Plasmaman Cargo Crate - Contains a Orange plasmaman space suit and helmet, along with a breathing mask and a emergency plasmaman tank. Costs 75 cargo points and requires EVA access.
-
-
-
20 March 2019
-
Dave-TH updated:
-
-
Krav Maga gloves can no longer steal the unstealable.
-
-
farie82 updated:
-
-
Fixed the middle mousebutton locking exploit
-
-
-
17 March 2019
-
AffectedArc07 and Alonefromhell updated:
-
-
Cell management consoles: See the status of all brig cells without having to leave your office
It is no longer possible to crawl into a vent while you are simultaneously buckled to a chair or other solid object.
-
-
farie82 updated:
-
-
Adds a confirmation to the start now verb. Make it ansari proof
-
The invisible bumping into something should be fixed now
-
Fixes the atmos bug
-
-
-
16 March 2019
-
Ty-Omaha and Ionward updated:
-
-
Carbon humans (people, not animals) who go SSD will now get ZZZ bubbles to indicate they are SSD
-
-
-
15 March 2019
-
Arkatos updated:
-
-
Fixes #10987 - Guardians can now see the action intent they are on
-
Added custom action intent icons for Guardians
-
-
Couls updated:
-
-
Added a new line to the defib examine text
-
-
-
14 March 2019
-
Couls updated:
-
-
tweaked shesi's fluff sprite
-
-
Quantum-M updated:
-
-
Changes the stamp sprites.
-
Add new sprites for the infernal and employment contracts.
-
Different organ sprites for each species
-
Different MMI sprites based on different species brains.
-
-
-
13 March 2019
-
Couls updated:
-
-
universal translate no longer makes emotes over comms impossible
-
fixed a few typos with simple mobs
-
-
-
12 March 2019
-
Arkatos updated:
-
-
Fixes #10261 - Pure Vampires in Traitor+Vampire gamemode will now properly show in AntagHUD
-
Fixes #9494 - Pure Changelings in Traitor+Changeling gamemode will now properly show in AntagHUD
-
-
-
11 March 2019
-
Couls updated:
-
-
Display if karma gains are enabled or not on round start(instead of just disabled)
-
Fix wrong message when toggling karma
-
-
rb303 updated:
-
-
Fluff scarf for Rb303
-
-
-
10 March 2019
-
AffectedArc07 updated:
-
-
You will now automatically be given admin rights if you connect to your local server
-
Mapmerge has been replaced with mapmerge2
-
Maps are now the TGM format. This means nothing for people who do not make map edits
-
Discord-related verbs are now under "Special Verbs" instead of "OOC"
-
-
Couls updated:
-
-
Toggle karma button in special verbs
-
-
Kyep updated:
-
-
Admins can now flag characters as having an event role, which makes them show up when admins look at the antag list, in admin attack logs, on antaghuds, and on the end-round score screen.
-
-
Tails2091 updated:
-
-
Added missing simple_animal emote help text.
-
-
TheMadTrickster updated:
-
-
added new fixed nice sprites
-
trashed old ugly buggy sprites
-
-
-
08 March 2019
-
AzuleUtama updated:
-
-
Fixed nuke ops cybernetic bundles giving 6 implants rather than 5.
-
Fixed nuke ops cybernetic bundles being delivered in a box that was then delivered inside another box. balance: Nuke ops shotgun ammo bags and cybernetic bundles can no longer be discounted.
-
-
Dave-TH updated:
-
-
Medical smartfridges now accept IV bags.
-
-
Jazz23 updated:
-
-
Golems loose their shell when they switch species
-
Mousedrop applies slime speed/chill potions.
-
-
-
07 March 2019
-
AzuleUtama updated:
-
-
Uplink items now use tooltips for their descriptions.
-
Uplink reformatted slightly.
-
-
Fox McCloud updated:
-
-
His Grace now allows you to toggle on/off binding to your hand
-
Activating his grace is now down by attempting to open it while it's in your hands
-
His Grace now removes slowed status, confusion, and resets shock stage if you're healthy
-
His Grace can now consume all mobs. Mobs consumed are permanently killed
-
His Grace will now neatly package up the inventory of people he consumes
-
-
Triiodine updated:
-
-
changes Neo-Russkiya Lang key to ?
-
-
-
04 March 2019
-
AffectedArc07 updated:
-
-
Fluff item
-
-
Arkatos updated:
-
-
Fixes #10815 - Cloned cultists now retain their Commune ability
-
-
Fox McCloud updated:
-
-
Hopefully fixes weird stack issues. Maybe. Who knows. The World can burn.
-
-
Kyep updated:
-
-
Hardsuits that can already carry RCDs in their suit storage slot can now also carry RPDs in that slot.
-
-
Nicaragua1 updated:
-
-
Genewul Giftskee is less annoying
-
Fixed Griefsky acces and drop
-
-
Triiodine updated:
-
-
Neo-Russkiya Language
-
-
craftxbox updated:
-
-
open button is separated more from previous href
-
-
datlo updated:
-
-
Shuttle hijacking is no longer interrupted by people cuffed, straight jacketed, or locked inside a welded/locked locker or wall locker.
-
Updated hijack's objective description to reflect the change.
-
-
-
03 March 2019
-
Fox McCloud updated:
-
-
Fixes genetic powers always activating when injected
-
Fixes Diona being able to be speedy and irradiate themselves with genetic powers
-
-
-
02 March 2019
-
Dave-TH updated:
-
-
Wall-mounted defib frames. Swipe an appropriate card to lock the defib in place and use it to save lives!
-
IV bags have been refactored and may now accept any chemical. Play around with them a bit!
-
-
Fox McCloud updated:
-
-
Fixes invisible stacks in hands
-
Fixes invisible bluespace crystals
-
-
Kyep updated:
-
-
Fixed cases of some genetics block SE injectors that are spawned at round start (such as the ones that can appear on the Sol Trade ship) not initializing properly, which would cause them to fail to work, and generate a runtime error. refactor: Did some minor refactoring to dna_injector.dm, fixing bad spacing.
-
-
Nicaragua1 updated:
-
-
Bots now drop their proper robotic arm
-
Honkbot drop is consistent with other bots
-
-
datlo updated:
-
-
Added navigation computers to the nuclear, SIT, SST, ERT, and vox shuttles. This computer lets you set a custom destination to jump to.
-
Most off-station shuttle consoles are now indestructible and impossible to deconstruct.
-
Added atmos blocking tiny fans and a security camera console to the ERT shuttle.
-
-
farie82 updated:
-
-
Can't use telepathy now when unconcious or dead
-
-
-
26 February 2019
-
Fox McCloud updated:
-
-
Adds in stable mutagen; a DNA altering compound
-
Having the max allowable number of advanced viruses will no longer confer total and complete disease immunity to *all* future viruses infections
-
Maximum number of advanced viruses you can have in your system at once reduced from 3 to 1
-
Removed stimulant symptom
-
Removed weight gain and weight even symptoms
-
Removed Sensory Destruction symptom
-
Sensory Restoration renamed to Mind Restoration.
-
Mind restoration functions largely the same as Sensory restoration, with a few minor number changes that adjust it downward ever so slighty. It no longer heals toxin or eye damage
-
Vision Restoration renamed to a more appropriate "Sensory Restoration"
-
Capulettium is no longer a perma-stun as long as it's in your system; keeps your paralyzed for the same time as it did previously.
-
Fixes edge case mutagen behavior
-
Adds upgraded cybernetic heart to R&D
-
can now repair robotic organs, outside of the body, with nanopaste
-
-
Kyep updated:
-
-
Pink terror spiders are now called Queens after they evolve.
-
The terror spider major event now has a princess variant, and no longer has a mother variant.
-
White terror spider infestations are now less predictable, more spread out over time, and affected by nutrition and some chems, but also have worse consequences if left completely untreated for a long time.
-
-
PidgeyThePirate updated:
-
-
changed a whole bunch of strings to add a bit more flavor to most reagents in the game (most of these can be found in the spreadsheet).
-
resurrected the old "flavor_strength" value which appears fully functional in testing but has been entirely unused.
-
-
Ralta updated:
-
-
Ian can now wear a CentComm Officer Beret to become Blueshield Ian
-
Sprite added for Blueshield armor to corgi_back.dmi
-
beret_centcom_officer and beret_centcom_officer_navy copied to corgi_head.dmi spritesheet
-
-
UmeFuu updated:
-
-
New recipe for cookies and sugar cookies, new ingredients such as pastry dough, flat pastry dough, unbaked cookies and a new tool called circular cutter (Added to the dinnerware vendor). New chem mix to create a specific type of dough for cookies and pastries.
-
Removed old cookie/sugarcookie recipe
-
added reagents of the cookies (They now actually taste like sugar and chocolate): - sugar = 3 - hot_coco = 5
-Also adjusted the sugar cookies nutriment from 3 to 1, just like chocolate cookies (They're made of the same dough after all) Chocolate bar can now be cutted into pieces/chocolate pile
-
added cookie(pastry) dough, flat cookie(pastry) dough, unbaked cookies/choco and circular cutter sprites. (Disclaimer: The cookie dough and flat cookie dough are edits of the normal doughs, pretty obvious but credits to who sprited them. Same with the tray with the unbaked cookies)
-
-
datlo updated:
-
-
Added a "voice" option to the magic mirror, letting you toggle comic sans/wingdings/swedish/chav
-
Free Golem Ship's interior walls and floors are now fully simulated titanium walls/floors, so they can be deconstructed, built upon, etc. balance: Increased the cost of RND boards for free golems to 2000 mining points (from 1500)
-
Golems can no longer activate robotic brains or have their brain put into an MMI.
-
Replaced one welding fuel tank in the golem ship by a chem master 3000.
-
-
farie82 updated:
-
-
Beepsky now can't insta cuff you when you run away and get back close to him.
-
-
-
24 February 2019
-
Fox McCloud updated:
-
-
Adds the compact syndicate sniper rifle to the uplink. A weaker, low capacity variant of the operative syndicate rifle
-
Fixes blindness mutation not making you blind
-
-
datlo updated:
-
-
Golems can no longer use telescience consoles.
-
Nuclear operatives can now choose to take over a cyborg when spawning one, with a ghost playing the nuclear operative.
-
-
-
23 February 2019
-
datlo updated:
-
-
Golems can no longer be objective targets
-
Offstation antag/special roles such as the ERT, abductors, etc, can no longer be objectives targets
-
Nukies no longer retain flavor text from saved character
-
Antag clowns can now toggle their clumsiness off and on.
-
-
-
19 February 2019
-
Citinited updated:
-
-
Using a multitool on a conveyor switch now switches between one and two directions without needing you to set it on a menu.
-
-
-
17 February 2019
-
Arkatos updated:
-
-
Changed Aurora Caelus event ending title to actually reflect that event is ending
-
-
Nicaragua1 updated:
-
-
Name of secbots
-
Honkbot wasnt dropping oil when exploded
-
-
-
16 February 2019
-
Alonefromhell & AffectedArc07 updated:
-
-
Tweaked the discord link alert text slightly.
-
-
Mitchs98 updated:
-
-
Bar Starter Kit to Cargo. 20 points for both Beer/Soda Boards and a package of glasses.
-
Beer and Soda Machines can now be wrenched to move them.
-
Beer and Soda Machines can now be constructed as well as upgraded to include a slightly wider range of drinks.
-
Properly named the Banana Honk to Banana Honk from Banana Mama.
-
-
Nicaragua1 updated:
-
-
Adds General Griefsky bot and a toy version!
-
Spin-sabre sound
-
Adds Griefsky sprites
-
-
Terilia updated:
-
-
Added the donksoft sniper rifle
-
special donksoft sniper foam darts & special foamforce sniper foam darts
-
Sniper Foam Boxes && Riot Sniper Foam Boxes.
-
creates an admin log, if a player is being hit by a Foam Dart which has been tinkered with.
-
fixes a small misalignment in the magazine sprite if a dart is loaded.
-
-
aleksix updated:
-
-
AI's "Wipe Core" now properly ghosts the player
-
-
farie82 updated:
-
-
Removes some of the chaplain special religion names
-
-
-
15 February 2019
-
aleksix updated:
-
-
posibrains and robobrains don't vanish upon the controlling player's suicide
-
-
-
14 February 2019
-
AzuleUtama updated:
-
-
Added Super Surplus Crates from TG. They contain 125TC worth of gear, but cost 40TC meaning you'll need to team up if you want one.
-
The Surplus chance value for various uplink items will now work when ordering a crate.
-
-
Citinited updated:
-
-
Adds jestosterone to the list of standard reagents, not sure if this has any in-game effect.
-
-
EmanTheAlmighty updated:
-
-
Sentience event now adds some damage to the affected mob.
-
Sentience event now adds health to the affected mob, rather than replacing the old value with another value.
-
-
Mitchs98 updated:
-
-
IV Drip crate can now be opened by general medical personnel, instead of only the CMO.
-
-
TDSSS updated:
-
-
NT rep and Magistrate lose access to the HOP office
-
-
aleksix updated:
-
-
made the lighter size consistent before and after first lighting.
-
-
datlo updated:
-
-
The Nuclear Authentification Disk can no longer be taken from the station by the ERT, Abductors, or Sol Traders.
-
-
-
12 February 2019
-
Citinited updated:
-
-
Fixes some spelling mistakes in the NT soul ownership contract
-
-
Kyep updated:
-
-
Added pink (princess) T3 terror spider, better terror spiderling AI.
-
Tweaked green and mother terror spiders. All terror spider types now have their own variants of the standard spider web.
-
-
datlo updated:
-
-
Added Greey's fluff duffelbag
-
Staff and wand of door can now also open lockers.
-
-
-
11 February 2019
-
AffectedArc07 updated:
-
-
Admins that linked their discord account that round no longer show up as "the adminkey" in adminwho.
-
Changelog button loads properly on darkmode now
-
Added an admin verb that allows admins to forcefully unlink discord accounts
-
-
Fox McCloud updated:
-
-
Cryotubes no longer passively heal patients without chems. Effectiveness at stabilizing critical patients increased
-
Sleepers no longer gain additional chemicals when upgraded. Selection of chemicals altered
-
-
Shadeykins updated:
-
-
Added Chav to roundstart character preferences.
-
Removed Epilepsy, Tourette's, and Can't speak properly from roundstart character preferences.
-
-
datlo updated:
-
-
Reworked golems to use the ghost spawner system. Craft a golem shell with adamantine then apply 10 sheets of minerals to finish it.
-
Added golem subtypes. Each material has pros and sometimes cons. Type depends on the material used during construction.
-
Golems are now more resistant to damage and are no longer slowed by the cold of space.
-
Golems now get golem-y names.
-
Fixed golem's stone face hiding their identity, showing them as unknown.
-
Added the Free Golems mob spawners and ship. Go do whatever.
-
Added a small asteroid on the telecomms zlevel.
-
Added Shesi's fluff winter coat
-
You can no longer use mob spawners (old station/golems) if you've forfeited your right to respawn.
-
-
-
10 February 2019
-
Fox McCloud updated:
-
-
Allows you to switch strap sides on leather satchel
-
-
TDSSS updated:
-
-
New space ruin, the crashed wizard shuttle. Rumored to contain fabulous magical treasures.
-
-
Ty-Omaha updated:
-
-
Reviver implant does not heal when you sleep, only when you fall unconscious involuntarily
-
-
-
09 February 2019
-
AffectedArc07 updated:
-
-
You can now link your discord account and BYOND account together
-
With the accounts linked, you can get roundstart notifications within discord!
-
Fixed roundstart message in discord so that people are notified instead of characters being replaced
-
-
Fox McCloud updated:
-
-
Adds Fox's fluff coat
-
Health HUDs now have a defib indicator showing if they can be revived with a defib or not
-
Defib "safe" time reduced from 5 minutes to 2 minutes
-
fixes a bug where sometimes revived individuals still appeared to be dead or severely damaged on health HUDs after being revived with a defib
-
-
MINIMAN10000 updated:
-
-
Configuration option for disabling subsystems
-
-
Quantum-M updated:
-
-
Headslug sprite looks more deader.
-
-
TDSSS updated:
-
-
Singularities can no longer be pushed
-
-
Triiodine updated:
-
-
ozewse fluff item
-
-
-
08 February 2019
-
Alonefromhell updated:
-
-
Drones should die properly now.
-
-
Kyep updated:
-
-
Characters are no longer massively more/less likely to be chosen for head jobs, especially the Captain job, based on their character's age.
-
-
Shadeykins updated:
-
-
Food descriptions/casing.
-
-
-
07 February 2019
-
Alonefromhell updated:
-
-
Pineapple Salad's fluff coat
-
-
Dovydas12345 updated:
-
-
Fixes cult shackles appearing on the ground when removed
-
-
-
06 February 2019
-
DrunkDwarf updated:
-
-
Reduced the size of the Ward-Takahashi Alt IPC head to prevent pixels clipping when wearing human clothing.
-
-
-
05 February 2019
-
Alonefromhell updated:
-
-
LDM and Sorium should no longer push/pull ghosts
-
-
Kyep updated:
-
-
fixed a "_logging.dm,85: Cannot execute null.simple info line()" runtime when xenobio slimes emoted.
-
-
-
03 February 2019
-
Fox McCloud updated:
-
-
Fixes a few edge cases of being able to create immunity to a few diseases
-
Adds suspiciously Voxy outfit to the game
-
Lack of breathing will render you unable to speak
-
-
MINIMAN10000 updated:
-
-
Boom function now properly checks for fuel
-
-
Tayyyyyyy, TaukaUsanake updated:
-
-
pAI units now have access to a flashlight module, which can be obtained with 5 RAM points.
-
-
-
02 February 2019
-
AzuleUtama updated:
-
-
Added Pack of C-4 for Traitors and Nuke ops. Comes with 5 C-4 charges for 4TC.
-
-
Kyep updated:
-
-
Made playtime numbers displayed to admins (in the playtime report) and players (in the 'check my playtime' verb) clearer in meaning.
-
-
MINIMAN10000 updated:
-
-
Mobs in help intent do not push mobs pulling a structure or the structure they are pulling
-
mobs standing on the same tile when being walked into on help intent.
Mob spawner menu buttons now work. This time it really works, I swear.
-
-
uc_guy updated:
-
-
Non-breathing mobs no longer cause an increase in germ level by not wearing a mask.
-
-
-
01 February 2019
-
AffectedArc07 updated:
-
-
Disabled darkmode is now normal grey, not full white
-
Changelog button now respects darkmode and will update when clicked
-
-
Citinited updated:
-
-
Sexy clown suits now have the squeak component
-
You can now change the way your sexy clown mask looks
-
-
Ty-Omaha updated:
-
-
Admin save feature in build mode will ignore mobs
-
-
datlo updated:
-
-
Wingdings now garbles sentences.
-
Clown and mime now have their ID properly updated to their new name after they rename roundstart
-
Added some ID photo outfits to some jobs missing it.
-
Agent ID photo editing refactored. The photo now looks the same as a real ID, with an outfit based on the job you've forged on the ID.
-
Agent ID should now be impossible to distinguish from a real ID by non-antagonists once properly forged.
-
You can now reset access or delete the agent ID's information without having to do both.
-
-
-
31 January 2019
-
Darkmight9 updated:
-
-
Adds the Camera Flash. A flash disguised as a camera for use as a cheap stun against non-sec, blinding crowds for a get away, and stunning borgs for emaging. Has a charge based system to prevent burning out.
-
Did some changes to flash code allowing different flashes to not be overcharged if one wants to or play a different sound when used.
-
-
Kyep updated:
-
-
Fixed various door control buttons that did not work correctly (brig prison lockdown, admin room lockdown, terror spider away mission containment doors, etc). refactor: refactored door_control buttons to check the GLOB.airlocks list, rather than doing a range(huge_number) check.
-
Terror Spider movement speed settings are no longer ignored when under player control. Instead, movement speed has been unified for both AI and player controlled spiders. Under player control, reds will now be slower, and purples will be faster. Under AI control, all spiders will be slower, except reds, which will be faster.
-
-
alffd updated:
-
-
revert to SS13 bot standard.
-
-
datlo updated:
-
-
Fixed surgery bugging and sometimes not starting properly when you try to surgery on a table or roller bed.
-
Surgery can now be done on any type of bed, with penalties.
-
Help intent is now required to start surgery. Was already needed to do surgery steps.
-
Surgery early cautery has been refactored. It is still done by holding a cautery in your inactive hand, but can now be done using ghetto tools, which can fail.
-
Medical cyborgs now have a laser scalpel instead of scalpel and cautery. lt is slightly faster and more versatile than standard tools.
-
Medical cyborgs now have a medical gripper. You can help patients up with it.
-
Medical cyborg can now cauterize incisions early by using the laser scalpel.
-
Added two black suit jackets to the arrivals locker room vendor
-
Added the armored suit jacket to the Bond, Payday, and Professional syndicate bundles.
-
Replaced the X4 in the Payday bundles by a C4.
-
The professional syndicate bundle now gets thermal fake sunglasses instead of thermal fake mesons.
-
Replaced the toolbox in the professional syndicate bundle by a pair of combat gloves.
-
Wingdings mutation works again.
-
-
-
30 January 2019
-
AffectedArc07 & Teri updated:
-
-
There is now a toggle-darkmode verb to switch darkmode on and off
-
Chat settings also has a dark mode
-
The icon for the server is now the paradise palm tree
-
-
Shadeykins updated:
-
-
New Russian statue
-
Moved some cables, swapped a vendor.
-
Fixed missing door button, some dupes, and unintended object behavior.
-
-
Terilia updated:
-
-
Added a notification about the chat reconnecting on toggling of the dark chat mode.
-
-
-
29 January 2019
-
Alonefromhell and Mitchs98 and farie82 updated:
-
-
Cake cat is now makeable.
-
-
Kyep updated:
-
-
Player-controlled hellhounds will no longer activate their smoke attack when they touch people on help intent.
-
Greater hellhounds (a far more dangerous version of the hellhound) now have descriptions that make it clear they are not the same as the regular hellhounds people are used to seeing.
-
-
farie82 updated:
-
-
fixes the viruses symptom creation being bugged. No more bluespace symptom creation
-
-
v0idp updated:
-
-
Discord Bot Functionality
-
-
-
28 January 2019
-
AzuleUtama updated:
-
-
Fixed Binary Key's description to give the correct code to use when communicating with the AI or borgs.
-
-
Ionward updated:
-
-
Ionward's fluff coat
-
-
Shadeykins updated:
-
-
New derelict station. New floortiles (brownfull, cautionfull, darkredgreen, darkredblue, darkredyellow) New trash subtype (spent ammo casings) New titanium walls subtype (nodecon) Minor/oblique lore references (USSP, TSF, Cult/Bluespace) Context/modified objects (custom descriptions, slogans, etc.)
-
Old derelict station, two suspicious toolboxes
-
Remap teleporter, DJ station
-
Clown shuttle missing adjacent wall tiles
-
-
datlo updated:
-
-
Abductors no longer start with your preset character's flavor text.
-
Abductor scientists now have their SE properly cleaned on spawn.
-
-
-
27 January 2019
-
Citinited updated:
-
-
Fixes tape being unapplicable to headsets and the autopsy scanner
-
You can't tape intercoms any more
-
The chemist can now create a new clown-based reagent using banana juice, lube, blood, space drugs, and salt.
-
Jestosterone heals brute damage for clowns, triggers annoying side-effects in other crewmembers, and is toxic to mimes.
-
-
Kyep updated:
-
-
fixed a runtime in hear_say.dm
-
Fixed item_attack / attack_obj runtime.
-
Fixed runtime when double-clicking a stool in-hand.
-
Antag objectives (kill, debrain, etc) can no longer target people on unreachable zlevels, like the admin-only/centcom zlevel.
-
fixed incorrect definitions of some spells related to shapeshifting.
-
Admin JMP links now work even if you're already following someone/something.
-
-
Kyep and alonefromhell and Ty Omaha updated:
-
-
Whispers are now fully readable in admin log.
-
-
TDSSS updated:
-
-
ether in syndie medical borg's hypospray replaced with hydrocodone
-
syndicate medical borg's hypospray no longer incorrectly lists its content
-
-
datlo updated:
-
-
Syndicate medical cyborgs now get a portable full body analyzer, making them much more effective field surgeons.
-
Bat swarm can no longer be spawned by gold slime extracts or reality tears. Regular bats can still be spawned.
-
-
-
26 January 2019
-
AzuleUtama updated:
-
-
C4 and X4 are now much better at destroying objects they are directly placed on.
-
-
Citinited updated:
-
-
Renames the "Bar" on the Centcomm level to "Bar Lounge".
-
-
Shadow-Quill updated:
-
-
The engineering outpost now has atmospheric blocking tinyfans in the mass drivers.
-
Changed the wall in the Kitchen/Botany vendor to a plating.
-
-
datlo updated:
-
-
Fixed bluespace bunny ears fluff item description
-
Chameleon flag reworked : Now cost 1 TC from 7, but starts without an explosive. It can be boobytrapped using any grenade or a syndicate minibomb.
-
Chameleon flag moved from "Explosives" to "Stealthy Tools" in the uplink.
-
Fixed description of syndicate flags on the suspicious supply depot.
-
Books now deal light damage on hit if you're not on help intent. Space law book deals extra damage.
-
-
-
25 January 2019
-
Agameofscones updated:
-
-
Cheeky Crenando's Soviet Greatcoat Fluff item.
-
-
Aurorablade updated:
-
-
Pineapplesalad fluff item
-
-
AzuleUtama updated:
-
-
Damp rags no longer have a lid, and must remain inferior to other containers.
-
-
Jazz23 updated:
-
-
Surgical Arm Menu
-
-
Kyep updated:
-
-
Fixed a mapping error in the brig remap PR.
-
-
blinkdog updated:
-
-
Normalized some paths in the code tree
-
-
datlo updated:
-
-
Reduced the cost of plasteel bomb frame crafting to 3 plasteel sheets (from 10)
-
Added emergency oxygen grenades to atmospherics lockers and the cargo emergency equipment crate.
-
-
warior4356 updated:
-
-
Drills now properly stop when turned off.
-
-
-
23 January 2019
-
AzuleUtama updated:
-
-
Various text and formatting changes to traitor items.
-
-
Dovydas12345 updated:
-
-
Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to grab decks of cards, paperbins, chairs, stools.
-
Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to split stacks of sheets.
-
-
Fox McCloud updated:
-
-
Fixes null crafting recipes
-
-
Ionward updated:
-
-
Updated some drink sprites!
-
-
datlo updated:
-
-
Added sprites for the SST hardsuit (Mostly black with dark red), sprited by Ionward
-
Mapped SST and SIT shuttles on deltastation map.
-
-
iantine updated:
-
-
Lumi's fluff mouse
-
Mice now use their rest sprite when resting
-
-
-
22 January 2019
-
TDSSS updated:
-
-
Suit Storage Units to most places that held hardsuits.
-
Ugly hardsuits on racks
-
reworked engineering slightly, removed the pointless hardsuit holding room.
-
-
Terilia updated:
-
-
Added Cake Cat - allowing the chef to create a living small pet in his kitchen.
-
Fixed frosted donuts, as they were filled with "spinkles" and not "sprinkles"
-
-
-
21 January 2019
-
AzuleUtama updated:
-
-
Backpacks will now give a rough indication as to how much space they have left when examining them.
-
-
Nicaragua1 updated:
-
-
added mining drone sprites
-
sound alert for vampire gamemode
-
clown bot
-
clown box (Its made stamping a piece of cardboard with a clown stamp)
-
"honkbot evil laugh"
-
clown bot and box sprites
-
honkbot sprites
-
-
Spartan6 updated:
-
-
Gives Sol Traders a baton and a cargo cap.
-
-
datlo updated:
-
-
RD, CMO, and CE greys will now properly get a translator implant if they need one.
-
Updated the Syndicate Strike team's gear and ready room. Syndicate commandos will now be wearing reinforced black elite syndicate hardsuits and pack more ammo and supplies.
-
Syndicate commandos no longer start with all access.
-
Fixed some issues and improved the usability of the SIT and SST shuttle blast doors. They can now be reliably used to lockdown your shuttle from NT would-be intruders, and can be opened from inside and outside.
-
Fix accidental revert of the Syndicate Forward Base area name
-
-
-
20 January 2019
-
AzuleUtama updated:
-
-
Fixed bee briefcase going into a negative number of remaining bees when used with less than 5 left.
-
-
Shadow-Quill updated:
-
-
You will no longer smack body scanner consoles when you rotate them.
-
-
datlo updated:
-
-
Fixed deathgasp emote not being called on death
-
Fixed nukies no longer exploding on death
-
-
-
19 January 2019
-
Alonefromhell updated:
-
-
Mulecloset killing machine has been fixed. Mulebots are no longer able to be put into closets.
-
-
Shadow-Quill updated:
-
-
Removed a description that gets overwritten, moved the current one to it's old location.
-
-
-
18 January 2019
-
Alonefromhell updated:
-
-
Revenant and Statue vision mode fixed.
-
-
AzuleUtama updated:
-
-
Added Professional Syndicate Bundle
-
Added Soporific Sniper Rifle. balance: Syndicate Bundles rebalanced to be worth more TC on average.
-
-
Nicaragua1 updated:
-
-
clown and mime locker now have correct acces
-
Golgrubs now run away from mechas being piloted
-
-
Quantum-M updated:
-
-
Medical Head Mirror, two spawn in the white medical clothes closet.
-
-
datlo updated:
-
-
Syndicate will no longer force you to play with the shiny new saboteur borg and instead send you the assault borg you actually ordered
-
-
-
17 January 2019
-
Eschess updated:
-
-
Jetpacks work properly when placed on suit slot
-
-
-
16 January 2019
-
Shadow-Quill updated:
-
-
Fixed a typo for when spiderlings enter vents.
-
-
uc_guy updated:
-
-
The burial suit (needed for the devil game mode) now shows up properly.
-
-
-
15 January 2019
-
Jazz23 updated:
-
-
Bluespace Closet
-
Bluespace closet animations/sprites
-
-
uc_guy updated:
-
-
Actually activates devil friends contract.
-
Adds employment cabinet and codex gigas.
-
-
-
14 January 2019
-
Kyep updated:
-
-
Doubled playtime requirements for command/sec jobs.
-
Starts tracking playtime on a per-department basis as well. E.g: "X hours in the Sec department".
-
Fixes bug which can cause more than 2 traders to spawn during the Sol Trader event.
-
Further improved sol trader event in general.
-
Enabled sol trader event to happen late-round as a randomly chosen event. Can only happen if the alert level is below red.
-
-
Quantum-M updated:
-
-
Magistrate Locker to the code.
-
Magistrate version of the Nanotrasen Navy Suit.
-
Gives the Magistrate a new wig, called Justice wig.
-
Magistrate specific stamp.
-
Adds the NT Rep version of the Nanotrasen Navy Suit (which already existed) to the NT Rep locker.
-
-
datlo updated:
-
-
ED bots no longer arrests you just because you have no ID by default
-
Nuke ops now spawn with their pinpointer.
-
-
-
13 January 2019
-
Aurorablade updated:
-
-
Fluff item for Asmerath. rscadd:Accordions now have inhands
-
-
Shadow-Quill updated:
-
-
Stopped emergency shield generators from magically unbolting themselves when they get turned off.
-
-
Superhats updated:
-
-
Vox, Drask, Diona and Grey can now choose the Neutral gender option.
-
-
datlo updated:
-
-
Nuclear operatives can now select the Saboteur module when picking a cyborg, a modified engineering module designed around stealth and sabotage.
-
Fixed an exploit allowing you to get free syndicate cyborgs.
-
-
lordPidey updated:
-
-
Infernal devils have been seen onboard our spacestations, offering great boons in exchange for your soul.
-
Employees are reminded that their soul already belongs to Nanotrasen. If you have sold your soul in error, a lawyer or head of personnel can help return your soul to Nanotrasen by hitting you with your employment contract.
-
Nanotrasen headquarters will be bluespacing employment contracts into the IA's office filing cabinet when a new arrival reaches the station. It is recommended that the lawyer create copies of some of these for safe keeping.
-
Due to the recent infernal incursions, the station library has been equipped with a Codex Gigas to help research infernal weaknesses. Please note that reading this book may have unintended side effects. Also note, you must spell the devil's name exactly, as there are countless demons with similar names.
-
When a devil dies, if the proper banishment ritual is not performed on it's remains, the devil will revive itself at the cost of some of it's power. The banishment ritual is described in the Codex Gigas.
-
When a demon gains enough souls, It's form will mutate to a more demonic looking form. The Arch-demon form is known to be on par with an ascended shadowling in power.
-
Added Devil agent gamemode, where multiple devils are each trying to buy more souls than the next in line.
-
If you've already sold your soul, you can sell it again to a different devil. You can even go back and forth for INFINITE POWER.
-
-
-
12 January 2019
-
AzuleUtama updated:
-
-
Chef Excellence's Special Sauce uplink description updated to be more accurate.
-
-
Shadow-Quill updated:
-
-
Fixed the QMs PDA supply app not showing the correct cargo shuttle location.
-
Changed the capitalization of CentCom and Station in the supply PDA cartridge.
-
-
datlo updated:
-
-
Nuke ops, ERT, and ayyybductors will now properly lose disabilities on spawn.
-
-
-
10 January 2019
-
Aurorablade updated:
-
-
Cap guns was checking for claiber type 'cap' when the ammo was set to caliber typer 'caps'. Fixed.
-
-
-
09 January 2019
-
Dovydas12345 updated:
-
-
Fixed NT Rep and Blueshield office door buttons not having correct required access
-
-
DrunkDwarf updated:
-
-
Analyzers now show the amount of moles within pipes and tanks
-
-
Fox McCloud updated:
-
-
Fixes glasses not properly masking eye-shine
-
-
datlo updated:
-
-
Added the Staff of Slipping to the wizard spellbook for 1 spell point, sprites by Mithrandalf.
-
Added the wizard clown outfit to the wizard vending machine.
-
Added the magic mirror to the wizard den, letting wizards swap to other species and change their appearance.
-
Added spare plasmaman suit, plasma tank, and vox internals to wizard robes racks for any wizard that wishes to change to these species.
-
Made the snack machine in wizard den free to use. (wizards don't take silly credits as currency)
-
-
-
08 January 2019
-
Alonefromhell updated:
-
-
Added an "All" option to ghost hud vision.
-
-
AzuleUtama updated:
-
-
Renamed and reorganized the ammunition in the uplink to make it easier for Nuclear Operatives to find the right ammo for their gun.
-
-
datlo updated:
-
-
Fixed grey translator translating the entire server.
-
Fixed BSA size checks being reversed, causing the BSA to clip through walls or prevent construction.
-
-
-
07 January 2019
-
Fox McCloud updated:
-
-
Fixes auto-injectors being free parapens
-
-
-
06 January 2019
-
AffectedArc07 updated:
-
-
Emitter reflectors are a thing now
-
-
Alonefromhell updated:
-
-
Dark matter and Sorium blob attacks should no longer affect ghosts and cameras.
-
All heads now have a HUD implant according to their department.
-
-
AzuleUtama updated:
-
-
New cane shotgun assassination shells. These buckshot shells are coated with a mute toxin which will prevent anyone hit either calling for help or screaming in pain.
-
Old cane shotgun assassination darts.
-
Cane shotgun now uses its own internal magazine rather than copying the code for the improvised one. It also now starts with an assassination shell preloaded.
-
-
Citinited updated:
-
-
You can now build snowmen out of 10 snowballs, 2 logs, and a carrot.
-
-
Dovydas12345 updated:
-
-
Added office door buttons, which open the office doors, to CE, HoP, CMO, HoS, RD, BS, NT Rep offices.
-
-
FreeStylaLT updated:
-
-
Christmas!
-
-
Mithrandalf updated:
-
-
Added toy handcuffs
-
-
TDSSS updated:
-
-
Variants of Suit Storage Units that are ID locked
-
SSUs can now be hacked. Old SSU maint panel menu removed.
-
IRC chassis now have titanium cost to produce on top of metal.
-
-
datlo updated:
-
-
Added new, different voice sets to Syndicate, Clown, Mime, and ERT/Dsquad mechs
-
Added voice modification kits to the exosuit fabricator, letting you swap a mech's onboard voice to another.
-
Added visual and audio warnings when your mech is running low on power
-
Added visual warning when your mech is locked by maintenance protocols
-
Capulettium fake death will now actually be convincing, fooling examine, medhud, and health analysers, but not body scanners.
-
Capulettium plus can now be used to manually fake your own death when you wish by resting, and wake up when you wish by toggling rest again.
-
Added fake death pill bottle to maintenance loot, contains 3 pills of capulettium plus.
-
Fixed a mech runtime when an empty mech used power.
-
Grey wingdings is now a disability, add it to your saved characters if you want to have them on.
-
Grey translator implant preference added. Translates speech to be comprehensible, the implant can be turned off and on at will.
-
Mutadone no longer removes genes that you have at round start, from your job, species, or disability you've picked in character creation.
-
Mutadone no longer removes powers gained from a completed DNA vault.
-
Removed syndicate uplink management consoles.
-
Nuclear ops now automatically get bonus TC from round start and war declaration split between their uplinks.
-
Nuke ops can now buy stacks of 50 TCs.
-
Added a regular internals box to the Honk Brand Infiltration Kit.
-
CC officers plasmamen now get an appropriate suit.
-
Updated admin-outfitted syndicates
-
Wizard forcewalls can now be walked through by the wizard summoning them.
-
Added a new spell to the wizard spellbook, "Greater Force Wall". Summons a larger wall than the regular one, but requires wizard robes.
-
Added one box of pill bottles to Scichem
-
Replaces one of the two crew monitor consoles in medical front desk by a medical record console.
-
-
improvedname updated:
-
-
Mindshield implant, is now shown by a green flashing outline of your job hud
-
Moves some huds around to make them not overlap
-
changes some icons
-
fixes two missing pixels on execute status
-
-
uc_guy updated:
-
-
Fixes active deswords being pocketable.
-
-
-
31 December 2018
-
Aurorablade updated:
-
-
Fixes Slaughter demons not releaseing corpses on death.
-
Fixes tears in spacetime just kinda sitting there.
-
-
Citinited updated:
-
-
Air pumps will now switch off when the inserted tank is removed.
-
-
Shadow-Quill updated:
-
-
No longer get debug messages from Slaughter Demons dropping mobs on death
-
Removed a useless comment in chronosuit code.
-
-
datlo updated:
-
-
Mech flashbang, banana, and mousetrap launchers now properly throw the item at your target instead of dropping it at the mech's feet.
-
Fixed nuclear operatives burning/choking on spawn if your set character is a plasmaman/vox. (they get healed once the round is done setting up)
-
-
farie82 updated:
-
-
Changed the laser tag gun pathing in the code.
-
Removed the / from the encryptionkey object in code.
-
Fixes the runtime in admin tickets
-
-
uc_guy updated:
-
-
Fixed death alarms / cell timer / beepsky radios.
-
-
-
30 December 2018
-
datlo updated:
-
-
Glowsticks now process fuel properly
-
-
-
29 December 2018
-
Alonefromhell updated:
-
-
Glowsticks are now compatible with shadowlings.
-
-
Spartan updated:
-
-
Adds emergency glowsticks to emergency box. sound: Glowsticks and flares now make more relevant usage sounds.
-
-
farie82 updated:
-
-
at the end of a radiation storm the maint access doesn't get revoked if it was set to emergency before hand.
-
-
-
28 December 2018
-
AzuleUtama updated:
-
-
"Grenades and Explosives" category added to the uplink. Anything classed as such in the uplink has been moved here for easier access.
-
-
Ionward updated:
-
-
missing drask crusader helm #10486
-
-
Kyep updated:
-
-
Added kangaroo, a new creature type that is initially passive, but can be dangerous if provoked.
-
-
Mitchs98 updated:
-
-
All movement / pull resistance has been moved over to tg's move resist system.
-
You now drop a pull by ctrl + clicking anywhere else on the screen, rather than the object/mob being pulled.
-
All atom movables now have move force and move resist, and pull force An atom can only pull another atom if its pull force is stronger than that atom's move resist.
-
Mobs with a higher move force than an atom's move resist will automatically try to force the atom out of its way. This might not always work, depending on how snowflakey code is.
-
As of right now, everything has a move force, pull force, and resist of 1000. Structures can be crushed with sufficiently big move_force.
-
Failing to move onto a tile will now still bump up your last move timer. However, successfully pushing something out of your way will result in you automatically moving into where it was. Makes moving much smoother.
-
Mobs that shouldn't be able to pull objects now use a better check to prevent it.
-
-
Spartan updated:
-
-
ERT Medics now spawn with a medical analyser upgrade.
-
Amber ERT now spawn with a flashlight.
-
Red Engineer ERT now have an Elite ERT Hardsuit.
-
Paranormal ERT now spawn with a seclite.
-
CE toolbelt renamed. grammar: Surgery Belt > surgery belt
-
-
TDSSS updated:
-
-
clumsy people are now properly bad at handcuffing
-
Holoparasites/Guardians using the say verb now use host communication
-
-
Tails2091 updated:
-
-
Mice can *squeak now.
-
-
datlo updated:
-
-
Added the ability for command to set emergency access on all station airlocks with the keycard authentification device. (ID swiper)
-
Added the Boots of Gripping to the wizard hardsuit, sprited by Ionward
-
Fixed a cast check missing plasmaman wiz suit, causing issues with spell icons for them
-
-
improvedname updated:
-
-
Syndi emergency box to nuclear opratives.
-
Moves the suicide pill to the emergency box
-
Adds a recipe for the toolbox to make it a suspicous toolbox
-
-
name here updated:
-
-
new hat in the autodrobe
-
-
uraniummeltdown updated:
-
-
RPDs should be available in hacked autolathes again
-
-
v0idp updated:
-
-
missiles shot from missile racks in mechs will no longer spin in air
-
banana cake and slice
-
-
-
26 December 2018
-
Shadow-Quill updated:
-
-
Fixed being able to start multiple prayers using the prayer beads.
-
-
v0idp updated:
-
-
Syndicate officer will not show in card modification/identification consoles anymore
-
-
-
25 December 2018
-
Ranged updated:
-
-
Mutadone removes dizziness immediately instead of taking 5 minutes
-
-
Ty-Omaha updated:
-
-
Fixes "makes frantic gestures" invalid emote with mute people using spells
-
-
improvedname updated:
-
-
fixed a typo
-
-
v0idp updated:
-
-
no bork in swedish accent while muzzled anymore
-
-
-
24 December 2018
-
Alffd updated:
-
-
Removed fart based mechanics.
-
-
Ty-Omaha updated:
-
-
Removes "name here" from PR template
-
-
datlo updated:
-
-
Added the grenadier belt for nukies, ported from tg, containing a LOT of various grenades to throw at people.
-
Added the gluon grenade (Freeze floors and irradiate) and the frag grenade.
-
Added Toxins tech to RND. Can only be improved by testing explosives in the toxins lab, and unlocks various atmospherics tanks and items in the protolathe.
-
Added the Bluespace Rapid Pipe Dispenser, allowing you to place pipes at a distance. Built in the protolathe after improving Toxins and Bluespace tech. Sprite made by Ionward.
-
Welding Gas Mask now requires toxins tech.
-
Syndicate Officer job now available for admins, along with a brand new office connecting to the SIT, SST, and nuke ops ready room.
-
Remapped SIT and SST starting areas to be next to nuke ops starting area. Added sleepers and a couple of other QOL stuff in their ready rooms
-
Added a holding cell to the SIT starting area
-
Added a teleporter available to SIT and SST if admin enables it, can go to and from the z2 area.
-
Added an armory SST can get if admin enables it. 2 bulldogs, 2 SMG, 1 sniper, 1 medigun, 1 rocket launcher and assorted ammo.
-
Added 3 dark gygaxes, tools, and welding fuel to the SST mechbay room (admin access required)
-
Added a new subtype of mech rechargers for CC zlevel that will always recharge an attached mech even without power/recharger monitor
-
Added SIT shuttle transit area
-
-
v0idp updated:
-
-
Syndicate Officer won't show in nt recruitment anymore
-
-
-
19 December 2018
-
Citinited updated:
-
-
Fixes a bug preventing snow machine crates from being orderable at roundstart. Ho ho ho!
-
-
uc_guy updated:
-
-
Fixed anomalies being disabled by random radio traffic.
-
-
-
18 December 2018
-
Citinited updated:
-
-
Adds the snow machine. Fill it up with water, turn it on, and watch it create a winter wonderland all on its own! For best results set your room's air alarm to the lowest value it can go to.
-
The snow machine is orderable from cargo during Christmas time.
-
You can use a shovel to clear away generated snow. Scrooge.
-
-
FreeStylaLT updated:
-
-
Christmas!
-
-
Ionward updated:
-
-
updated santa hat sprite, use hat to toggle beard
-
-
Tails2091 updated:
-
-
Fixes vent crawl vision sticking around for simple_animals.
-
-
datlo updated:
-
-
Added a global cap on printing papers.
-
-
-
17 December 2018
-
MarsM0nd updated:
-
-
Restores mech radial menu functionality.
-
-
-
15 December 2018
-
MarsM0nd updated:
-
-
radial menu now works for normally implanted implants
-
-
datlo updated:
-
-
Added sprites to specie specific boxes made by shazbot
-
-
uraniummeltdown updated:
-
-
Me button added to chatbar
-
-
-
13 December 2018
-
Breenland updated:
-
-
Adds drask ability to have auto-accent.
-
-
Edefff updated:
-
-
increase rollie smoketime to accommodate new chem volume
-
-
Kyep updated:
-
-
Tweaked the syndicate depot to fix various bugs and unintended design things, as well as make some changes to improve fun value.
-
Computer and machine frames are no longer invincible, and can now be destroyed by hostile NPCs.
-
-
McDonald072 updated:
-
-
Fixed being unable to cast lightning with the action button.
-
-
Mitchs98 updated:
-
-
Add's Makiroll's! Larger sliceable variants of sushi that yield four rolls of sushi in the same time that it previously took for one. You can also eat the Makiroll itself for 4x the nutriment/protein of a regular roll of sushi. Requires the Sushi Mat to craft.
-
Add's the Sushi Mat. 3 start in the chef's vendor. New ones craftable with 5 wood and 5 cable coil.
-
-
Shadow-Quill updated:
-
-
Makes people who are miming/mute give a visible indicator of their communion.
-
-
Tails2091 updated:
-
-
trimmed 300ms delay from smash.ogg
-
-
datlo updated:
-
-
Removed access requirement on emagged fax machines
-
-
-
12 December 2018
-
Kyep updated:
-
-
Fixed a few things that should not be possible with pAIs and AIs.
-
-
Tayyyyyyy updated:
-
-
Read only sec hud for IAA and blueshield
-
-
name here updated:
-
-
Fixed Bulldog and C20 having their ammo alarms only go off once per gun.
-
-
-
11 December 2018
-
Alonefromhell updated:
-
-
Miniature energy gun now has an action icon for it's light toggle(like flashlight).
-
-
Azule Utama updated:
-
-
Syndicate Uplink now uses expandable and collapsible categories. General layout of the uplink has also been changed to work alongside this.
-
-
Birdtalon updated:
-
-
Species specific starting boxes.
-
-
Citinited updated:
-
-
Fixes a runtime caused by AIs watching dance machines
-
You can now tape much more than just paper!
-
You can now order a crate full of sticky tape
-
Maximum amount in a tape roll is now 25 (up from 10).
-
Fixes some issues and runtimes in floorcluwne code.
-
Admins will now be informed of a new floorcluwne's chosen target if one is provided via the event.
-
There's a button next to secure storage's blast doors now.
-
-
Darkmight9 updated:
-
-
Added overheal to nanopaste
-
-
Ionward updated:
-
-
fixed slight spriting errors
-
added some more grey headwear
-
-
Kyep updated:
-
-
Fixed runtime related to chaplains.
-
Player-controlled giant spiders will no longer unintentionally poison anyone they nuzzle on help intent. They can still poison people they bite.
-
Altered the warning you get when you try to put one bag of holding inside another, so it is absolutely clear what this does, and there is no chance someone can do so by accident.
-
-
MarsM0nd updated:
-
-
Arm implants use radial menues where suitable
-
Item actions can have icons different from the icon of the item
-
-
MrKicker updated:
-
-
Sorting of call list for holopads
-
-
Shadow-Quill updated:
-
-
Makes the chem-master update it's icon on power change, as well as showing the correct sprite after being loaded in.
-
Changed Oldstation Air Alarms/APCs to no longer give warnings to the main station.
-
-
TDSSS updated:
-
-
ghost spawn menu jump and spawn buttons now work.
-
-
Tails2091 updated:
-
-
Fixed typo for Schrodinger's cat.
-
-
datlo updated:
-
-
Display case burglar alarm no longer triggered if there's no power to equipment
-
-
gangelwaefre updated:
-
-
Aesthetic changes to Lumi's custom sprites
-
-
-
10 December 2018
-
Farie82 updated:
-
-
Can't become 1 pixel big anymore due to genetics
-
-
-
06 December 2018
-
Shadow-Quill updated:
-
-
Fixed protocol spelling in the Photon Projector description.
-
-
TDSSS updated:
-
-
Reverted holopad sorting to make holopads work again.
-
-
-
01 December 2018
-
Kyep updated:
-
-
Fixed a couple of bugs with the special event pets triggered by admin bless command.
-
-
TDSSS updated:
-
-
Ancient Station asteroids now contain minerals and can be mined.
-
-
datlo updated:
-
-
Added 3 carrot seed packets to perma.
-
-
-
30 November 2018
-
Azule Utama updated:
-
-
Fixed an ORM exploit which would let you smelt invalid stacks of alloys.
-
-
TDSSS updated:
-
-
Removed ballgag and assless chaps
-
-
-
29 November 2018
-
Kyep updated:
-
-
Updated chaplains. They now spawn with their nullrod in their hand, and their soulstone in their locker. They now have the ability to bless other players. The more players they bless, the more likely admins are to answer their prayers. There are no longer any atheist chaplains. The chaplain items that reference atheism have been tweaked accordingly, e.g the atheist fedora is now the binary fedora. A few other items have also been tweaked. Paranormal ERT members now count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful version of the nullrod, so they have a reason to use a weapon other than their gun.
-
-
TDSSS updated:
-
-
No more making infinite meat and crashing the server with gibbers
-
-
-
28 November 2018
-
Kyep and FoS updated:
-
-
Updated hellhound with new sprites by FoS, slightly better AI, and more fixes/tweaks.
-
-
MrKicker updated:
-
-
Sort callable holopads by name
-
-
tigercat2000 updated:
-
-
You can now speak in multiple languages in the same message! This works for all forms of speech, including radios. Minus megaphones because fuck em.
-
Some mild formatting errors and inconsistencies that have historically been present within mob speech.
-
Holopads behaving a bit weirdly with how they interact with the typical say system
-
-
-
27 November 2018
-
Azule Utama updated:
-
-
Power beacon made purchasable again in Nuke Ops uplinks.
-
-
Dovydas12345 updated:
-
-
Fixes being able to attach IV drips when incapacitated
-
-
Farie82 updated:
-
-
You can now actually make the rescue jaws
-
-
-
26 November 2018
-
Citinited updated:
-
-
Adds the rubbish bin in front of the kitchen again
-
-
TDSSS updated:
-
-
Medbay secondary storage is now accessible to everyone with medbay access, hardsuits were put behind a windoor with CMO access to keep them at the same level of accessability.
-
Added and removed some items from medbay secondary storage.
-
Medical storage and secondary storage were renamed to be more accurate.
-
-
datlo updated:
-
-
Updated description of finger gun to point out you can holster the gun manually by using it in hand.
-
Fixed a bug where you couldn't learn finger gun if you already knew fake finger gun.
-
Power beacon cost reduced to 10 TC, and is now hijack-exclusive.
-
Guillotines can now be deconstructed with a welder.
-
-
-
25 November 2018
-
Azule Utama updated:
-
-
Job-specific gear can no longer be discounted.
-
Discounted items now get an alternate log entry stating the item's new price.
-
-
KasparoVy updated:
-
-
Fixes Unathi Snout 2 not using the correct sprite.
-
Fixes Unathi Points Head not using the correct sprite.
-
Fixes Unathi Sharp Tiger Head and Face not using the correct sprite.
-
Fixes Unathi Tiger Head and Face not using the correct sprite.
-
Removes Unathi Sharp Points Head and enables Unathi Points Head marking for use on all Unathi head types.
-
-
MarsM0nd updated:
-
-
Coins will now always show a side on being spawned.
-
-
Reagent Scanner Changes updated:
-
-
Removed Mass Spectrometer and Advanced Mass Spectrometer
-
Reagent Scanner and Advanced Reagent Scanners can now identify blood types
-
-
datlo updated:
-
-
Added the Advanced Mimery Series to Syndicate Mime uplink.
-
Added a fake Finger Gun manual to the arcade prize machine.
-
Changed the look of the teleporter hallway from maintenance to dirty hallway.
-
-
-
24 November 2018
-
Azule Utama updated:
-
-
Added uplink discounts. Traitor and Nuclear Operative uplinks now have a discounted gear section! 3 random items will be chosen to be 50% off (rounded down), 25% if they usually cost 20 or more TC. You can only buy a discounted item once per uplink. Ported from TG.
-
-
Eschess updated:
-
-
hardsuit helmets now unlink from the hardsuits upon being detached
-
syndicate hardsuit helmet combat mode can no longer be toggled on hand
Space ruin/gateway hardsuits now should all come with helmets
-
Telecom setup in wizard gateway can now be completed with the present stock parts.
-
-
Ty-Omaha updated:
-
-
Added reflective blobs, these blobs have a high chance to deflect energy projectiles while being vulnerable to ballistics and brute damage. Reflective blobs can be obtained by upgrading a shield blob.
-
-
tigercat2000 updated:
-
-
Fancier Transpara-corner Nano take 2.
-
Nano's build-watching works on 512 again.
-
Nano scrolling issues with the power monitor (they existed before I touched this goddamnit I swear!!!)
-
Rewrote Nano's buildscripts and upgraded all the dependencies (again)
-
-
-
23 November 2018
-
Azule Utama updated:
-
-
Additional check added to damage falloff code, will only delete bullets that reach 0 damage if they actually have a falloff value.
-
-
Kyep updated:
-
-
Dead mice no longer squeak.
-
Ghosts walking over living mice no longer makes them squeak.
-
-
TDSSS updated:
-
-
no more runtime spam each time a simple mob is attacked
-
-
datlo updated:
-
-
Replaced "illegal" and "weapon" in strange objects name
-
-
-
22 November 2018
-
AlAtEX updated:
-
-
re-adds sprites for boxes that disappeared
-
-
AlAtEx updated:
-
-
Added a new medkit for IPCs
-
added a purple medkit
-
Added a repair kit box to start with for IPC's
-
Re-added the crowbar and extended tank to miner's boxes
-
added three new box images
-
-
Azule Utama updated:
-
-
Made laser tag guns work again.
-
Syndicate Cigarettes added to maintenance loot.
-
-
Eschess updated:
-
-
Adds ui button to toggle hardsuit helmet
-
syndicate hardsuit combat mode is activated only by the helmet button
-
-
Kyep updated:
-
-
Added hellhound, a dangerous new monster.
-
-
datlo updated:
-
-
Added the CQC manual to nuke ops and traitor uplinks, letting them remember some of the basics of CQC.
-
-
-
21 November 2018
-
MrKicker updated:
-
-
Added generated sound files to sound/vox_fem , then added references to them in vox_sounds.dm
-
-
-
20 November 2018
-
AffectedArc07 updated:
-
-
NTTC now has multiple job tag styles
-
NTTC now has option to make job tags colored
-
NTTC now has option to make nametags colored
-
NTTC now has options to make command members louder (bold)
-
The NTTC window title is no longer NTSL.
-
-
Azule Utama updated:
-
-
Fixed chameleon suit having two invalid options.
-
-
TDSSS updated:
-
-
Silencers now have a tech origin, give research levels when deconstructed
-
Moved gun attachments to their own folder, code-wise.
-
-
name here updated:
-
-
Fixed a runtime in a syndieteam radio.
-
-
tigercat2000 updated:
-
-
Nano scrolling is 95% less buggy
-
NanoUI's Fancy Mode now less broken as hell remove: 512 support for Nano dev tools
-
-
-
19 November 2018
-
Birdtalon updated:
-
-
Fixes a runtime in safe.dm
-
-
Citinited updated:
-
-
Alt-clicking a jumpsuit removes accessories from it
-
Removing an accessory now shows a small message
-
-
KasparoVy updated:
-
-
Brings the logging of plasma statue ignition up to the same spec at as welder tank explosions.
-
You can no longer ignite plasma statues with disablers.
-
-
Kyep updated:
-
-
Tweaked many of the special admin outfits. This means centcom officers are less likely to be seen wielding illegal syndicate gear, and subtle flaws with many other outfits (such as pirates lacking radio, singulo knights lacking a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) have been addressed.
-
Added several new admin options for fax responses, blessings, and smiting.
-
-
Quantum-M updated:
-
-
Sleeping carp uplink description now points out that it is unable to be learned by vampires or changelings.
-
Holoparasite kit uplink description now points out that it doesn't work on vampires or changelings.
-
Attempting to learn sleeping carp as a changeling or vampire gives you a red warning message.
-
You can now refund the sleeping carp scroll to the uplink.
-
-
TDSSS updated:
-
-
A warning if slings are very close to ascension, so the crew can potentially still stop them
-
-
craftxbox updated:
-
-
add observer/incapacitated check for all sec/medhud actions
-
-
datlo updated:
-
-
Added antag alert sounds that play at roundstart for most major antagonists, ported from TG.
-
-
-
17 November 2018
-
uc_guy updated:
-
-
Syndicate borgs are no longer pseudonymous on syndie radio.
-
-
-
16 November 2018
-
Azule Utama updated:
-
-
Changed falloff damage to be usable on any desired projectile rather than just shotgun pellets. balance: X-ray lasers now use 100 charge per shot (previously 50). balance: X-ray laser guns now have falloff damage. The longer the laser is in the air, the lower its damage becomes.
-
Slight addition to X-ray laser's description.
-
-
Certhic updated:
-
-
Replaces radio freq magic numbers with constants
-
-
Farie82 updated:
-
-
Borgs can't get perma stunned anymore by goliaths and slings and such
-
-
Fethas updated:
-
-
The floors are not safe! HONK!
-
-
Jazz23 updated:
-
-
Added flasher buttons in perma brig as well as windoors in botany, the wardens office, and cargo. Also added blast doors to transit tube.
-
HoP's flasher button not working, CE's secure shutter button and transit tube lockdown button not working.
-
-
Kyep updated:
-
-
The admin verb to list SSD players now highlights players who are another player's antag target. Additionally it lets you despawn players whose body is already in cryo.
-
Fixed a bug which caused banning to fail in rare situations.
-
-
Mitchs98 updated:
-
-
You can no longer rip the hood part of a hoodie off of someone's head.
-
Bee Costume and Monk Robe icons now show up properly in your inventory.
-
-
Triiodine updated:
-
-
Hotfixes taser projectiles being borked due to X-Ray re-work.
-
-
tigercat2000 updated:
-
-
SPEEEEEEEED to the asset cache, making preloaded UI assets transfer much faster.
-
NTTC deserializing works again
-
NTTC regex works again
-
NTTC no longer spams admins
-
NTSL2 no more, it is officially NTTC
-
NanoUI's fancy mode is hot shit again!
-
NanoUI's fancy mode is no longer broken as hell!
-
512 support for Nano dev tools
-
-
-
15 November 2018
-
Azule Utama updated:
-
-
Fixed an exploit which allowed cultists to curse the shuttle more than twice. Steve can only take so much punishment ya know...
-
-
Certhic updated:
-
-
The scrollbar of NanoUI now looks more Nano-ish
-
The title bar of NanoUI now sticks while scrolling
-
changed the mouse hover behavior on the fancy NanoUI buttons
-
-
Dave-TH updated:
-
-
Internal bleeding is now represented by coughing (And occasionally vomiting) blood! Nifty!
-
-
uc_guy updated:
-
-
Fixed the passive effects of prayer beads and prayer bread.
-
-
-
14 November 2018
-
KasparoVy updated:
-
-
Vulpkanin Earfluff can be selected in facial hair again.
-
Vulpine Fluff and Earfluff head accessories and facial hair now have correct icon states.
-
-
uc_guy updated:
-
-
Borgs no longer have infinite roller beds.
-
-
-
13 November 2018
-
Birdtalon updated:
-
-
Fixes playtime self checker.
-
-
Certhic updated:
-
-
fixed a cigs runtime error
-
-
TDSSS updated:
-
-
Ancient station's lockdown is now lifted correctly.
-
Ancient station RD console can now be used.
-
-
craftxbox updated:
-
-
use mob voice instead of mob name for radios broadcasting signals.
-
-
datlo updated:
-
-
Prevent wizards from casting rod form inside the wizard den.
-
-
-
12 November 2018
-
Azule Utama updated:
-
-
Fixed text errors in the descriptions for Booger cocktails and Feral cat grenades.
-
-
Birdtalon updated:
-
-
Verb to check your own playtime.
-
-
CornMyCob updated:
-
-
You can now unwrench and move the library machines/computers, chem master, chem heater, washing machine, pandemic and PDA painter
-
-
Farie82 updated:
-
-
Added the pressure damage reduction to mining bots. No more killing machines called mining bots.
-
-
variableundefined updated:
-
-
AI can now select the alien screen display
-
Nearly every single sprite accessories (species customization option) has been separated and refactored. Report missing hairstyle / screen / horns / frills / tails etc.
-
Desolate's peacekeeper fluff cyborg sprite is now his service sprite.
-
-
-
11 November 2018
-
Azule Utama updated:
-
-
Borgs can no longer stunbaton into infinity. Their batons will now deactivate if they have no power left after hitting someone and cannot be turned back on until they recharge.
-
-
Eschess updated:
-
-
large cardboard boxes now show their size when examining
-
fulltile plasma glass windows now have armor
-
rised plastitanium windows integrity
-
-
Farie82 updated:
-
-
You can now hurt mining bots with welders on any attempt other than help
-
Can put suits and such back into the suit storage units
-
Fixed the tank/magboots storage part being called Breathmask storage, lazy copy pasta
-
-
Squirgenheimer updated:
-
-
Hatched alien larvas will default to being created on the turf of the mob instead of the mob's location, unless specifically allowed (like closets and spacepods)
-
-
tigercat2000 updated:
-
-
Ears are now an organ, which can be damaged, removed, and inserted!
-
Human icon code should perform massively better.
-
-
-
10 November 2018
-
Citinited updated:
-
-
Prevents an infinite metal exploit using the autolathe.
-
Minimum returnable metal of ammunition boxes has been lowered from 2000 to 500.
-
-
Dovydas12345 updated:
-
-
Fixes being unable to slice certain food grown by hydroponics (pineapple, watermelon etc.)
-
-
Shazbot updated:
-
-
Some fancy new box sprites, props to Shazbot for the sprites
-
Old cuff box is gone
-
-
TDSSS updated:
-
-
Quarantine is now its own lawset.
-
-
-
09 November 2018
-
Alonefromhell updated:
-
-
Most sheets held in hand should now display either a metal or reinforced glass icon where appropriate.
-
Holopad should no longer automatically revert to default sprite.
-
-
Azule Utama updated:
-
-
Small change to cursed heart's spellbook description.
-
-
AzuleUtama updated:
-
-
RCD now gives visible messages when building without enough ammo or on an invalid tile.
-
-
Citinited updated:
-
-
Fixes ghosts being able to make conveyors drain more power than they should.
-
-
Dave-TH updated:
-
-
Space levels is named now.
-
-
Mitchs98 updated:
-
-
Chemical implants now work and can be properly filled via beaker or syringe. Reagents inside can also be syringed out.
Added drill and safe intenral sprites made by Shazbot194
-
-
-
08 November 2018
-
Citinited updated:
-
-
Conveyors use less power now
-
-
Eschess updated:
-
-
fixes the NOR, NAND and XOR logical gates
-
reinforced plasma glass windows give you reinforced plasma glass sheets now
-
fulltile reinforced plasma glass windows now have armor
-
-
Farie82 updated:
-
-
Mining bots now function as expected when giving them a health upgrade. No more repairing without healing
-
-
Fel updated:
-
-
You can now craft wooden barrels with 30 pieces of wood! They can hold up to 300u of reagents.
-
Putting hydroponics-grown plants into the barrel lets you ferment them for alcohol! Some give bar drinks, while others simply give plain fruit wine.
-
Reagent containers like bottle & glass should be more consistent now.
-
-
Spartan updated:
-
-
Plastic bags and wet floor signs can now spawn in maint.
-
Plastic bags are now supplied to your syndicate uplink. Apply directly to head.
-
-
Wario4356 updated:
-
-
Mecha can now drill other mecha
-
-
Warior4356 updated:
-
-
Mecha drills now tell you when they can't drill
-
-
datlo updated:
-
-
Added the Toxins Payload Casing to crafting recipes, a new method of activating tank transfer valve bombs.
-
-
tigercat2000 updated:
-
-
Mecha now use action buttons instead of ugly verbs.
-
Mecha weapons can now be selected through a radial menu brought up by Ctrl Clicking on the Mecha while you are piloting it.
-
Tooltips now appear on radial menu buttons when you hover over them. Seriously, why wasn't this a thing in the first place?
-
Action button icons are now located in their own file.
-
Captain and HoS can be nearsighted again.
-
-
variableundefined updated:
-
-
Baycard, including tarot cards to loadout
-
Baycard to prize machine
-
All non-syndicate card deck on map has been replaced with bay card.
-
-
-
07 November 2018
-
Spartan updated:
-
-
Bluespace Crystals no longer use the entire stack when used on self to teleport.
-
-
Squirgenheimer updated:
-
-
toggling off global antag candidacy will disable you from being selected by the Create Antagonist verb.
-
-
TDSSS updated:
-
-
added mulebot control to captain's PDA again.
-
-
name here updated:
-
-
objective lists are now sorted for admins.
-
-
uc_guy updated:
-
-
IPCs and slimes now have an effect on the floor when bleeding.
-
-
-
06 November 2018
-
R1f73r updated:
-
-
Added a death text to headslugs when they die
-
-
Squirgenheimer updated:
-
-
blob and autotraitor game modes will now check for Global Antag Candidacy when picking new antagonists after round start
-
Global Antag Candidacy button will now show up after round start
-
-
TDSSS updated:
-
-
Can no longer attempt to build tranquilite walls (and delete the wall in the process)
-
-
TatsumakiMagi updated:
-
-
target icon updates when lit by user
-
-
Triiodine updated:
-
-
Airlock sensors & vent system to west mining outpost (Safety first!)
-
Disposals inlet now directly goes to cargo _delivery_ (not conveyor)
-
More spawns for science nerds in accordance to highpop.
-
All conflicting C_tags, dispatch cops or AI should freely use all cameras now.
-
[delta] APC to virology mainroom
-
[delta] All unsimulated turfs are now simulated.
-
-
Ty-Omaha updated:
-
-
Fixes spacing in admin deletion logs
-
-
datlo updated:
-
-
Added syndicate themed internals to traitor spacesuit and hardsuit.
-
-
-
05 November 2018
-
AzuleUtama updated:
-
-
Added Traitor's toolbelt
-
Replaced Military belt with Traitor's toolbelt in the uplink.
-
Price of new belt lowered to 2TC
-
Replaced Military belt with Traitor's toolbelt in maintenance loot.
-
-
Regen updated:
-
-
The tentacle changeling power now generates admin logs.
-
-
TatsumakiMagi updated:
-
-
Fixes adjacency and standing checks for cutouts
-
-
-
04 November 2018
-
AffectedArc07 updated:
-
-
Makes status display font crispy. mmmmmmmmmmmmm
-
-
Citinited updated:
-
-
Fixes a bug in machines when switching between speedy and normal processing speeds.
-
-
Dave-TH updated:
-
-
Adds the access tuner, a syndicate device for interfacing with airlocks. Try it out!
-
-
Farie82 updated:
-
-
Clings now appear dead on medical huds when using regenerative stasis
-
-
R1f73r updated:
-
-
Admin Character names will no longer appear in adminhelps
-
-
TDSSS updated:
-
-
Allow , in names, Kidan of the world, rejoice
-
Made kidan random name generation less shitty
-
-
Triiodine updated:
-
-
ghost role sprites with a palette more depressed than the playerbase
-
medical doc spawn to ghost station
-
Xydonus's second fluff item
-
-
-
03 November 2018
-
Certhic updated:
-
-
Added diona nymph action buttons
-
Added diona nymph resist alert when they're merged
-
Diona nymph can now initiate merge with the gestalt
-
Diona nymph can now leave their gestalt by resisting
-
Diona nymph can no longer attack its gestalt
-
-
Farie82 updated:
-
-
Security comments now work again. Sec hud arrests will now function as intended.
-
-
Fox McCloud updated:
-
-
Fixes exploit involving materials and the recycler
-
-
Jazz23 updated:
-
-
A method of uploading coordinates to perma teleporter circuit board.
-
-
variableundefined updated:
-
-
Tigercat2000 & variableundefined (Ansari) to the maintainer list.
-
-
-
02 November 2018
-
Purpose updated:
-
-
After over 100 years in cryosleep, a few cryocells are starting to open... AncientStation ghost roles are now available.
-
Adds a ghost role menu, available under the Ghost menu
-
Adds an all-access Air Alarm for mappers to utilise.
-
Adds glowsticks. Currently only available in AncientStation.
-
-
variableundefined updated:
-
-
Attack log to stun gloves
-
-
-
01 November 2018
-
Citinited updated:
-
-
A disposal nullspace bug.
-
-
Farie82 updated:
-
-
Repairing a mech now says you're doing it to the others balance: Mechs now take time to repair. No more spam repairing
-
Random news feed now does not contain random code.
-
-
Mitchs98 updated:
-
-
Lowers the spam you receive from entering a warm or cold pool. You will no longer receive 'The water is quite warm.' nearly every few seconds.
-
Headslugs no longer teleport out of closed lockers upon bursting.
-
-
Warior4356 updated:
-
-
Ghosts can no longer re-enter a drone that has been shut down.
-
-
-
31 October 2018
-
Arkatos updated:
-
-
Fixes Rewriter drink description typo.
-
-
Jountax updated:
-
-
Renamed Ice Peppers to Chilly Peppers.
-
-
TatsumakiMagi updated:
-
-
fixed merch shop, arcade shop and the give command working from a distance
-
-
-
30 October 2018
-
Dave-TH updated:
-
-
Adding a paper to a paper bundle no longer automatically opens the bundle.
-
-
Farie82 updated:
-
-
Items dropped in a space pod are now under the seat. No more magical dropping out of the pod
-
Cargo can now buy oil tanks.
-
-
Warior4356 updated:
-
-
Megaphone now handle speech impediments properly
-
Swiping an ID through a drone no longer causes a runtime and correctly shuts it down
-
Silicons are now able to open a door linked to a button regardless of proximity
-
-
uc_guy updated:
-
-
You can no longer table people through walls/doors/shutters.
-
-
warior4356 updated:
-
-
fixed the holosign in surgery1
-
-
-
29 October 2018
-
Farie82 updated:
-
-
Round start time is now variable. Defaults to 240 if not filled in
-
-
Mitchs98 updated:
-
-
Re-Adds a Guest Pass terminal to Medbay front desk.
-
-
Squirgenheimer updated:
-
-
regular mining satchels will now only hold 10 slots of ore stacks instead of 50
-
Deleting mechs no longer causes a runtime
-
Mech speech bubbles should now follow the mech.
-
-
gatchapod updated:
-
-
Fixed airlocks electrocuting people remotely through open UI
-
-
-
28 October 2018
-
Dovydas12345 updated:
-
-
Fixed being able to pull when incapacitated
-
Fixes catching two handed items with one hand.
-
-
Fox McCloud updated:
-
-
changes the oil can sprite
-
Colorful Reagent changes your blood color
-
-
Mitchs98 updated:
-
-
Adds the Security Jacket to the standard sec gear lockers, an alternative to the standard armor vest that covers more area but protects less. Style matters.
-
-
Normalyman updated:
-
-
Fixed being able to open containers via dragging, while being incapacitated.
-
-
Ty-Omaha updated:
-
-
Pulling fixed
-
Better way of fixing hostile mobs not attacking
-
Hostile mobs attack again instead of nuzzle
-
-
uc_guy updated:
-
-
Fixes shadowling game mode delaying the game ticker
-
-
-
27 October 2018
-
AffectedArc07 updated:
-
-
Removed catgirls, be gone foul beasts
-
-
Alonefromhell updated:
-
-
Runtime in species.dm, 620 fixed
-
Stable LDM and Sorium creates their vortexes properly now.
-
Inject chems into all your favorite types of smokeables, TODAY!
-
Backend: Added dummy vortex reagents to prevent further runtimes.
-
-
Certhic updated:
-
-
fixed wrenched down unconnected pipes being invisible
-
fixes invisible diona observers
-
Fixes simple animals attacking while they were on help intent.
-
-
Farie82 updated:
-
-
Dusting a mob now dusts everything he holds and has equiped
-
fixes animals activating the paperfolding proc. No more runtimes there
-
One less piano runtime
-
fixes the runtime in the AI code. You now get messages if you lose power and stuf.
-
Fixes the runtime in Landmarks
-
-
TDSSS updated:
-
-
HoP's door remote has access to his office doors + supply doors now
-
-
tigercat2000 updated:
-
-
Pretty radial menu for the RCD!
-
SSoverlays human mobs
-
Catgirls!
-
/tg/'s catgirl refugees
-
Ears are now organs
-
The suffering of thousands of displaced kittens
-
-
uc_guy updated:
-
-
Fixed roller beds not going to their "down" position.
-
You can now tell if a borg has suicided by examining them
-
-
-
26 October 2018
-
Mitchs98 updated:
-
-
Unary vents, scrubbers, passive vents, connectors, air injectors, and pipe caps now orientate as intended when using Orientate Automatically with an RPD.
-
Fixes #8036, Door controls not respecting range for pod doors.
-
Now when holding a flag it won't be stabbing into your characters face. Burning a flag also won't magically change its orientation.
-
-
dovydas12345 updated:
-
-
Fixes ghosts being able to unflip flipped tables.
-
-
uc_guy updated:
-
-
Syndicate communication channel is now pseudonymous.
-
-
-
25 October 2018
-
Aurorablade updated:
-
-
welders will now fix external IPC leaking. My Bad.
-
-
Birdtalon updated:
-
-
User responses not being appended to admin tickets
-
-
Dave-TH updated:
-
-
Adds surgical trays! You can drag these cool tables around and the items placed on them come along for the ride! Nifty!
-
-
Farie82 updated:
-
-
Objectives now get fully removed when removing them admin style. Removing the assassinate cryo message if you were de antagged.
-
-
tigercat2000 updated:
-
-
PiP Hud Elements
-
AI PiP Multicam - Enabled by admins
-
Calling /New( with excess arguments is now properly directed to /Initialize(
-
-
-
24 October 2018
-
Alonefromhell updated:
-
-
Mind check in pre_quip added, to prevent runtime.
-
-
Birdtalon updated:
-
-
Backend cleanup of assembly.dm and proximity.dm
-
-
Certhic updated:
-
-
Runtime error in CureIfHasDisability
-
Borg health is now updated after being repaired
-
-
Farie82 updated:
-
-
Tablets now spawn correctly. No more buying (seemingly) broken tablets
-
-
Fethas updated:
-
-
Ipcs bleed oil. Bleeding can be patched by welders and organ mainp surgery(if you have to heal an ipc via surgery we may as well take that out too).
-
Kidan biolum slightly brighter. tweak:Vox now become confused and unintellible(..more) on cort stack damage.
-
-
Warior4356 updated:
-
-
Safe tumbler 2 no longer makes I am open noise when turning tumbler 1.
-
-
dovydas12345 updated:
-
-
Added data disk to misc designs.
-
-
variableundefined updated:
-
-
Using reagent dispenser like fuel and water tank no longer give you an attack cooldown / animation.
-
Tracking for shadowling win rate. Improved parsability for other win/loss round type's win rate.
-
-
-
23 October 2018
-
Alonefromhell updated:
-
-
You should now be able to put all your favorite chems in food again.
-
-
Fox McCloud updated:
-
-
Reagents now GC slightly better
-
-
-
22 October 2018
-
Dave-TH updated:
-
-
Fancy tables now properly smooth.
-
-
MrStonedOne updated:
-
-
Fixes a cause of lag in the Timer subsystem
-
-
Purpose updated:
-
-
Removes unused code in Nuclear gamemode.
-
Removes some empty icon files.
-
Fixes a typo in an SDQL parse warning.
-
Code improvement with timers in Revolution gamemode.
-
-
name here updated:
-
-
The autopsy scanner now works even when it does not know the weapon and/or the time of death.
-
Unused weapon chance code
-
-
uc_guy updated:
-
-
Removed logging ambiguity for uplink purchases.
-
-
variableundefined updated:
-
-
Component refactor from tg made by ninjanomnom has been ported over. Report unexpected issue (with autolathe / ORM)
-
-
-
21 October 2018
-
Alonefromhell updated:
-
-
Fixed some formatting issues in post_equip.
-
-
Ansari updated:
-
-
Oculine processing should be less expensive now.
-
-
Desolate updated:
-
-
Refactors some reagent lists into global list
-
-
Farie82 updated:
-
-
Cyborgs can now refill welding tools and fire extinguishers using the recharging station
-
Oculine now updates the blindness status correctly
-
Added the Viral Injector. A virologist specific traitor item that acts like a sleepy pen but can transfer viruses. It's disguised as a functional pipette.
-
-
Purpose updated:
-
-
Moves Icon Smoothing to a Subsystem.
-
Atom code will no longer track a list atoms, for literally zero reason.
-
Fixes grammatical error in the suit storage unit
-
-
Shazbot194 updated:
-
-
all north facing in hand icons for flags.
-
-
Squirgenheimer updated:
-
-
Explosive holoparasite booby traps will now behave better, such as correctly triggering on mobs
-
-
Triiodine updated:
-
-
Skrell & Tajaran sechardsuit to paracode palette, from Bay12 palette.
-
TG & BS12 sec-hardsuits in all dmis
-
-
Warior4356 updated:
-
-
Final UI update was missed in Safe Refactor PR
-
-
name here updated:
-
-
Holodeck plating sprite is now back to the old one.
-
-
tigercat2000 updated:
-
-
We're going 512 boisssssssssssssss
-
-
variableundefined updated:
-
-
Improves the List free slots admin verb to show useful information.
-
Cyborg hypospray's attack log message should no longer be reversed.
-
How containers work is now standardized in the back-end. There might be unexpected or odd bugs with containers and reagent transfer, please report them.
-
Minor refactor of revenant code.
-
Some relative path & commented out code has been cleared up in code. Report unexpected issues.
-
-
-
20 October 2018
-
Birdtalon updated:
-
-
Spacepods explosions are significantly reduced.
-
-
Dapocalypse updated:
-
-
Adds password protected files to modular computer.
-
-
Farie82 updated:
-
-
Guardian injectors now tell in their examination text if they are spend or not.
-
Added feedback on the RCD airlock access topic.
-
-
Fox McCloud updated:
-
-
Updates the Garbage SS so it's less likely to induce lag
-
-
Purpose updated:
-
-
Suit storage units now contain magboots for relevant roles.
-
Adds the captains jetpack to his suit storage unit, so it is now stealable again on Delta.
-
Aluminum & Aluminium properly standardized.
-
-
craftxbox updated:
-
-
added check to make sure person downloading pAI isnt dead.
-
-
uc_guy updated:
-
-
It is no longer possible to duplicate uvents.
-
-
variableundefined updated:
-
-
Plating's icon is back to the old one once again.
-
-
-
19 October 2018
-
Fox McCloud updated:
-
-
Fixes round-start sparks being stuck in maintenance
-
-
Purpose updated:
-
-
Fixed an issue with Space Vine mutations
-
-
SpaceManiac updated:
-
-
The body zone selector now indicates which body part you are about to select when hovered over.
-
-
TDSSS updated:
-
-
New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter ripleys.
-
-
Triiodine updated:
-
-
new DNA Sampler Sprite
-
-
Warior4356 updated:
-
-
Added nanoui for safe. Added minor quality of life to safe.
-
Removed old UI from safe
-
Safe now is only Right - Left - Right. Safe is 0-99 rather than 0-71.
-
Added safe dial for it's nanoui.
-
-
-
18 October 2018
-
IrkallaEpsilon updated:
-
-
Feral Cat grenades are now listed as job specific items.
-
-
Shazbot updated:
-
-
Shazbot's custom cyborg sprites.
-
-
Squirgenheimer updated:
-
-
Ghosting from cryopods with an inventory open should no longer cause a runtime
-
-
Triiodine updated:
-
-
disposals pipes sprite offsets & stray pixels.
-
id_decal icons
-
arcade id_decals using mind batterer sprite. (That's just silly.)
-
-
-
17 October 2018
-
Alonefromhell updated:
-
-
Added a Nanotrasen Navy Uniform to the blueshields locker
-
-
Crazylemon updated:
-
-
Buildmode is now compatible with 511 clients.
-
-
FalseIncarnate updated:
-
-
Floodlights will now shut off if lacking a power cell.
-
-
Fox McCloud updated:
-
-
Fixes the Timer SS timing out when it shouldn't
-
Fixes reagent overdose runtimes
-
-
TDSSS updated:
-
-
Examining a borg tells you what module it has loaded
-
-
datlo updated:
-
-
Added the Honk Brand Infiltration Kit to Nuke Ops.
-
-
-
16 October 2018
-
FalseIncarnate updated:
-
-
Corpse spawners (such as those on the Wild West away mission) now properly spawn corpses at roundstart that don't remain standing.
-
-
-
15 October 2018
-
FreeStylaLT updated:
-
-
Crunchy sounds when bones are broken
-
-
Squirgenheimer updated:
-
-
Changelings will now wake up after using Regenerative Stasis.
-
-
TDSSS updated:
-
-
The maximal length of a name that won't be rejected as a 'bad name' has been raised.
-
-
Ty-Omaha updated:
-
-
Fixes stunbaton runtime (Stun() being called on a turf)
-
Borers with their "Dominate" window already open can no longer run across the map and successfully cast the spell on those people, they must be within 7 tiles (default view range)
-
Borers can no longer spam open the "Dominate" spell
-
Borers with their "Dominate" target window already open can no longer successfully target someone if they are dead
-
Borers no longer "slither up and probe people's ear canal" if they select the target of an "infect host" spell after they die
-
-
uc_guy updated:
-
-
You can no longer roll around when dead.
-
-
-
14 October 2018
-
Purpose updated:
-
-
Makes it so that Screwdrivers & Wirecutters are no longer invisible in the map editor.
-
Fixes a gibbing runtime
-
-
taac updated:
-
-
added cryo cell description
-
-
uc_guy updated:
-
-
fixed runtime in IsBanned.dm
-
-
variableundefined updated:
-
-
Stacks are split by CtrlShiftClick instead of AltClick now.
-
A runtime that occurs with paper bundle being created with one or less paper.
-
-
-
13 October 2018
-
Birdtalon updated:
-
-
Chem master now will show its de-powered state properly.
-
-
DarkPyrolord updated:
-
-
Changed attack log level for reagent forcefeeding from FEW to MOST
-
-
FlimFlamm updated:
-
-
Tweaked formatting of Newscaster stories
-
Fixes images displaying improperly on Newscaster stories
-
-
Ty-Omaha updated:
-
-
Boxing logs moved to the ALL preference
-
-
alex-gh updated:
-
-
Species damage modifiers now only affect damage, not healing.
-
Races that took more damage from certain damage types no longer heal from that damage type faster. For example: Drask no longer heal from burn at double rate; Grey, Vox no longer heal from brute at increased rate (Note: IPC healing with welders/wires is not affected).
-
Kidan no longer heal from brute at a reduced rate.
-
-
uc_guy updated:
-
-
You can no longer get an infection and die during abductor surgery.
-
Voice analyzers no longer activate on noise.
-
-
-
12 October 2018
-
Alonefromhell updated:
-
-
META - Cargo shuttle blast doors now reacts to the right button.
-
META - Cargo shuttle airlocks now bolt properly.
-
META - Cargo shuttle flaps are now airtight. All hail Cargonia.
-
-
Birdtalon updated:
-
-
Gamma ERT Paranormal gets their null rod.
-
Moves check_and_add() to reagents holder
-
-
DesolateG updated:
-
-
Refactors global var lists to use the global subsystem.
-
-
Farie82 updated:
-
-
Added the on_give proc for items. Was needed for the fixes
-
Giving two handed items like the DIY chainsaw and potted plants now works correctly
-
The DIY chainsaw, doomslayer chainsaw and the potted plants now do damage when given to somebody else and when picked up while the chainsaw was on.
-
-
Purpose updated:
-
-
Cyberiad's grimy tiles are now actually dirty and cleanable.
-
Delta's grimy tiles are now actually dirty and cleanable.
-
Ironsand is now visible in the Map Maker.
-
Away missions updated with the appropriate dirt/grime so that it is now cleanable.
-
Fixes stool's unique suicide message.
-
Fixes rollerbeds no longer going through plastic flaps.
-
-
TDSSS updated:
-
-
Removed Skrell discrimination, allows ! character in IDs (agent IDs or made via ID computer)
-
-
variableundefined updated:
-
-
Ore now represented by stack that holds up to 50 items. Should reduce lag with ORM greatly.
-
Satchel can only carry ten items instead of 50 items. You should end up carrying more ore in total however
-
Fire acting on ore means they would be refined with 50% efficiency.
-
Stack merges automatically if dropped on the floor, or a new stack is created. This doesn't happens on your body.
-
They also merge if you drag them over eachother.
-
Alt-click split a stack
-
You can throw sand into people's eyes! Pocket sand!
-
Phazon take 5 bluespace crystal to construct now instead of 1. remove: Transfer prompt when you click on a stack of the same type with a stack
-
-
-
11 October 2018
-
Citinited updated:
-
-
Fixes an oversight in autopsy report drawer's description.
-
-
Farie82 updated:
-
-
NPC's now initialise correctly. Removing a lot of runtime errors.
-
-
Kyep updated:
-
-
Fixed the admin ERT panel not working correctly if the admin using it was playing as a carbon mob.
-
-
Stork Industries updated:
-
-
Fixes "Arachno-Man's" boots
-
-
Triiodine updated:
-
-
SLOT_MASK from necklaces.
-
thatdanguy23's fluff item
-
-
-
10 October 2018
-
Alonefromhell updated:
-
-
You should no longer be able to relight a burned match by using a shoe.
-
-
Birdtalon updated:
-
-
Small runtime in tickets.dm
-
Mulebot teleportation exploit.
-
Iron sand icons now render correctly.
-
-
Citinited updated:
-
-
Emagging a locker will keep the original description instead of telling you it was emagged twice.
-
Examining airlocks displays the proper icon now
-
Holopads don't work when unanchored any more.
-
-
Purpose updated:
-
-
Fixes a few broken tiles in maintenance, by breaking those tiles properly.
-
-
Purpose & AndrewMontagne updated:
-
-
New grimy dirt sprites.
-
Dirty tiles now get dirtier if neighbouring tiles are also dirty.
-
-
Triiodine updated:
-
-
new sprites for cup-chicken soup, icecups, weight loss shakes.
-
cup to can of chicken soup.
-
-
Ty-Omaha updated:
-
-
Fixes PAIs
-
Ambulances work again
-
-
Warior4356 updated:
-
-
added Grey sprite for psysuit, made by dumbdumb
-
-
tigercat2000 updated:
-
-
Hovering over an inventory slot now shows an indicator for if that item can go in that slot or not. Pretty!
-
SSOverlays has been added, but not implemented!
-
-
-
09 October 2018
-
Alonefromhell updated:
-
-
Edited the attack text of the teleport armor.
-
-
Birdtalon , LPSpartan, Shazbot, Memager updated:
-
-
Portable Body Analyzer for ERT
-
Muilti Lens Immolation gun for gamma ERT
-
PDW-9 sidearm for ERT
-
T4 Thermite Charge for Gamma ERT security
-
Sprites for gamma ERT suits
-
Red ERT loadouts
-
Gamma ERT loadouts
-
-
Citinited updated:
-
-
Conveyor belts have received a facelift!
-
Rotating a belt with a wrench now nicely rotates the belt for you
-
Click a lever with a lever to link their IDs. Click a belt with a lever to link that belt to that lever.
-
Deconstructing a syndicate console will no longer ruin it forever.
-
-
DesolateG updated:
-
-
Refactors the timer subsystems and bugfixes
-
-
Purpose updated:
-
-
Code improvements on mouse_opacity
-
Plating shadow faux 3d now works properly.
-
-
Purpose & AndrewMontagne updated:
-
-
Adds tile smoothing to plating. Plating should now be a bit more of a 3d look...
-
-
Purpose & Birdtalon updated:
-
-
Takes Runtime out of the oven.
-
-
Squirgenheimer updated:
-
-
fixed a potential runtime in the sentient animal event
-
-
Triiodine updated:
-
-
Tidied up nuclear shuttle's mini-medbay to better utilize the space provided.
-
Full Body-Scanner, surgery set, replacement limbs, bloodpacks to the nuclear shuttle's mini-medbay.
-
One of the nuclear shuttle's sleepers.
-
-
uc_guy updated:
-
-
Legless human mobs no longer scream non-stop when buckled into a chair.
-
-
variableundefined updated:
-
-
Poolcontroller performance are improved dramatically. Expect slightly reduced CPU use on beach gateway map
-
Poolcontroller will no longer work properly if you directly var-edit someone's location to inside a body of water and a decal's (However if the mob move right after it will still work)
-
-
-
08 October 2018
-
Ansari, Birdtalon updated:
-
-
Updates resting procs, fixes getting people up from help intent.
-
-
Birdtalon updated:
-
-
Conservation of damage mechanic for set species
-
Changeling transform conserves damage when transforming to a different species.
-
-
Crazylemon updated:
-
-
Fixes AIs being unable to examine due to a runtime.
-
Fixes nearsighted glasses behavior being inverted (seeing worse with glasses).
-
Mining mobs now update their sprites on death.
-
-
Crazylemon64 updated:
-
-
Updates for damage on HUD elements are now instant for cyborgs and humans.
-
When dead, you can now see your surroundings with ghost vision and examine things around you.
-
-
Farie82 updated:
-
-
PANDEMIC can print a virus release form now. Viromancers REJOICE!
-
-
Purpose updated:
-
-
Adds the missing turfs under windows & doors on Mech Transport Space ruin.
-
Fixes improper turf in the shuttle crashed into one of the space ruins.
-
Fixing improper decals & missing turfs in the Space Bar space ruin, and some tiny fixes.
-
GasTheLizard Space Ruin now uses Decals properly.
-
MoonOutpost19 Away Mission now uses Decals properly.
-
Evil Santa Away Mission now uses Decals properly.
-
Fixes the corpse spawners in Space Battle Away Mission.
-
Space Battle Away Mission now uses Decals properly.
-
Prettier Donate/Karma buttons!
-
Adds new stair sprites.
-
Blackmarket Backpackers now uses Decals properly.
-
OneHalf Space Ruin now uses Decals properly.
-
CentComm Away Mission now uses Decals properly.
-
Cyberiad Z2 now uses Decals properly.
-
Space Hotel Away Mission now uses Decals properly.
-
Terror Spiders Away Mission now uses Decals properly.
-
Adds plasma window spawners for mappers.
-
Thrown stunbatons & improvised batons have a low chance to stun.
-
You can now alt click breath masks to pull them up & down.
-
You can no longer erroneously pull down a vox mask.
-
TravisCI now checks all space ruins & away missions for integration.
-
-
Triiodine updated:
-
-
Rsik's fluff katana ~~modkit~~
-
-
Ty-Omaha updated:
-
-
Replaces Security's bomb suit with their cooler Security version
-
Fixes runtime in world.dm;127
-
-
tigercat2000 updated:
-
-
Made mind.dm 1/1000 less awful.
-
-
variableundefined updated:
-
-
NPCpool (SNPC) is now a subsystem.
-
NPCAI (For simple mob) is now a subsystem.
-
Customising SNPC no longer results in screaming death and a naked person.
-
Logging added to RD teleport gun, some projectile are always logged
-
EMPulse & Explosion can optionally log a cause for administrative purpose
-
Backend Attack logs now display coordinates of attacker & defender for forensic reconstruction.
-
Grill shock cooldown is 1 second instead.
-
-
-
07 October 2018
-
Birdtalon updated:
-
-
Ammo boxes now return materials proportional to their contents when recycling, nullifying infinite ammo exploit.
-
-
Farie82 updated:
-
-
Fixing a disability now fixes the gene related to it if needed. No more free gene stability from blindness and such
-
fixed bluespace disposal bins
-
instant recall doesn't fuck up disposals
-
meteor shots now deconstruct the disposals unit, removing weird behaviour
-
-
Purpose updated:
-
-
Winged chairs now get placed back down correctly as winged chairs.
-
CyberiadAI Discord Bot now announces which station is being used.
-
Less things will refer to the NSS Cyberiad when not actually ON the NSS Cyberiad.
-
Decals now Initialize()
-
-
SkeletalElite updated:
-
-
Fixed grammar in meat spike's name
-
Chaos Holoparasite's abilities actually work
-
-
datlo updated:
-
-
Changelings with wingdings now permanently switch to regular speech after transforming
-
-
variableundefined updated:
-
-
All sharp items can cut sliceables like cheesewheel now.
-
Putting items inside sliceables is done by alt-click now.
-
-
-
06 October 2018
-
Alonefromhell updated:
-
-
META - Cryogenics now has a Cellcharger.
-
-
Purpose updated:
-
-
Delta - Adds a Paramedic's Office.
-
Latejoining autotraitors should now have their uplinks again.
-
You can now pick up most chairs and beat colleagues with them. Careful too many whacks and they'll break.
-
Adds new bar stools.
-
Delta - Removes extra door in arrivals.
-
-
Squirgenheimer updated:
-
-
Victims of changeling swap forms and wizard mindswap can now re-enter their corpses
-
-
-
04 October 2018
-
Alonefromhell updated:
-
-
Sensory Restoration should now work with Ocular Restoration.
-
-
Farie82 updated:
-
-
borgs can now heal their patients while there is a surgery going on.
-
-
Purpose updated:
-
-
Boxstation: Fixed a number of turf/decal/overlay issues
-
Boxstation: The poster in medbay maintenance now displays properly...
-
Boxstation: Xenobio slime cameras should no longer be able to see into maintenance.
-
Boxstation: Adds missing firelock to vacant office.
-
Boxstation: Moves Medbay AIR Alarms around to more functional locations.
-
Boxstation: Fixes 'fake grass' in the kitchen area.
-
Boxstation: Fixed several issues were Radiation Storm events could bleed into maintanence.
-
Boxstation: ALL catwalks should now be able to see space through the holes.
-
Delta - Adds fuel depo to the hanger.
-
Delta - Adds the Nullrod & Shard to the Chaplain's back office.
-
Delta - Fixes the invisible wardrobe in the dorms.
-
Delta - Adds a few art vendors across the station.
-
Delta - Adds the buttons to the Perma Airlock.
-
Delta - Doctors now have access to the patients rooms. Oops.
-
Delta - Adds the Coroner's spawn point in the morgue.
-
Delta - Increases blood packs in medbay, by random blood spawners.
-
Delta - Fixes the exit button of Medbay.
-
Delta - Increases the size of the atmos space loop.
-
Delta - No longer can maintenance fire lasers at the Supermatter....
-
Delta - Added some wiring to make it easier to emitter the SM.
-
Delta - Extends the wiring out of solars airlocks in atmos solars.
-
Delta - Atmos now have access to Atmos solars.
-
Delta - Adds an additional atmos void suit.
-
Delta - Adds two additional engineering void suits, but into secure storage.
-
Delta - Fixes the missing airlock cycling on an atmos airlock.
-
Delta - Adds the missing multi-tool to atmospherics.
-
Delta - Fixed Mixed Air & Gas Mix computers access to the tanks & sensors.
-
Delta - Can now cross parts of the transit tube.
-
Delta - Garbage disposal is now functional.
-
Delta - Disposals no longer fires trash into the atmos office.
-
Delta - Atmos techs now have access to the jetpacks in EVA.
-
Damaged plating when fixed, now loses the aesthetic damage too.
-
Yellow closets now use the correct icons.
-
-
-
03 October 2018
-
Farie82 updated:
-
-
Your hands won't become the surgeons hands anymore in surgery
-
-
Fethas updated:
-
-
Cryostorage ghost role spawners for ruin/mapping/adminbus. Also refactors corpse landmark code.
-
-
FreeStylaLT updated:
-
-
Remapped Medbay Lobby.
-
Moved the cell charger from Cryo to the break room.
-
Added a cell to Medbay's break room.
-
-
-
02 October 2018
-
Birdtalon updated:
-
-
Small formatting fix in soulstone.dm
-
-
Kurgis updated:
-
-
The chief engineer jumpsuit no longer appears as a green suit when held in-hand.
-
Added a new in-hand sprite for the chief engineer jumpsuit from Polaris.
-
-
Purpose updated:
-
-
Delta Station, codenamed Kerberos has been acquired by Nanotrasen.
-
Wizard Academy now uses decals
-
Wizard Academy misplaced wires fixed
-
-
Tails2091 updated:
-
-
Claw Game is now a bit easier to use. Slower speeds, still receive prize when interrupted, and auto-close.
-
Claw Game has correct window size, centered buttons, general code cleanup.
-
-
name here updated:
-
-
Remove canvas and easel from Deltastation
-
-
tigercat2000 updated:
-
-
Chat no longer horribly breaks at the first high-ascii character.
-
-
-
01 October 2018
-
Aurorablade updated:
-
-
adjusts to Arachno-Man suit fluff.
-
-
Birdtalon updated:
-
-
Admin ticket subsystem - migrates existing global datum.
-
-
Dapocalypse updated:
-
-
Added a grille cooldown to prevent alt-click spam someone on a grille to instantly husk people.
-
-
Farie82 updated:
-
-
Not being able to place chutes over tiles with multiple pipes.
-
-
Purpose updated:
-
-
CPU Performance in get_area proc
-
Excavates a few relics from area code.
-
Metastation - Escape Shuttle windows are now breakable again.
-
Metastation - Medbay camera no longer floating in mid-air.
-
Metastation - Adds the missing component analyzer to Robotics.
-
Metastation - Fixes the wiring issues in Medbay.
-
Metastation - Fixes the wiring issues in Virology.
-
Metastation - Fixes the lack of fungus on the map, placing it near water sources in maintenance.
-
Metastation - Fixes area definition, so that admins can now send people to cryo.
-
Metastation - Fixes bizarre map corruption from the Arcade PR which turned Coroners into a bit of an arcade....
-
Metastation - Law office's shutters now grant privacy properly.
-
Metastation - Fixes the lack of inflatables & pipe painter in Atmospherics
-
Metastation - Adds a second atmos locker, as one is lower than number of atmos slots available....
-
Metastation - Properly marks airless tiles by the hanger as airless.
-
Metastation - Hooks up Security's Camera Computer to the station's cameras...
-
Metastation - Fixes the floating fire alarm in Security.
-
Metastation - Fixes the detective's lack of Evidence Storage access...
-
Metastation - Captain, IAA and NT Rep's fax machines are hooked up properly. Bloody IT department...
-
Metastation - Security cannister attachment is now attached to the pipe grid.
-
Metastation - Bots now correctly patrol the station again.
-
Metastation - Updates the turfs & decals to use the correct decals.
-
-
Purpose & AndrewMontagne updated:
-
-
Tiles now retain the styling when damaged.
-
Tile damage now uses decals, and can be mapped easier.
-
-
TDSSS updated:
-
-
RnD server control console's data management now works, allowing for deletion of research levels and known techs.
-
fixed minor typos.
-
bluespace polycrystals can now correctly be broken down while floating in space.
-
-
variableundefined updated:
-
-
Nano Mob Hunter ported to StonedMC. Report unexpected issues.
-
Shuttle has been ported over to the StonedMC Subsystem.
-
-
-
30 September 2018
-
Crazylemon updated:
-
-
Corrects a comment in the code regarding IPC damage.
-
-
Purpose updated:
-
-
Fixes various message format overflows.
-
-
Shazbot updated:
-
-
You can now remove KA mods from borgs.
-
-
TDSSS updated:
-
-
Plasma statues and walls are no longer ignited by laser tag guns or practice lasers.
-
Crowbars can no longer make pool water invisible.
-
-
datlo updated:
-
-
Made the poison pen available to traitor librarians
-
-
variableundefined updated:
-
-
One click antagonist giving antag to people in restricted job.
-
-
-
29 September 2018
-
Dapocalypse updated:
-
-
Removes extra penlight given to plasmemes.
-
-
DarkPyrolord updated:
-
-
Pyro's fluff item
-
-
Kyep updated:
-
-
Fixed several bugs with blob, including lateround blobs not generating biohazard alerts, blobs missing out on early resources they should have, and a bug with blob storage being broken that prevented blobs getting any resources.
-
-
NoWolfie updated:
-
-
New Pyr'kus cult floor and wall sprite.
-
-
Triiodine updated:
-
-
Nukies spawning with cybernetic organs/limbs
-
-
Ty-Omaha updated:
-
-
Removes canvases due to everybody crashing from them.
-
-
farie82 updated:
-
-
Headbutting the airlock is more consistent.
-
refactored the airlock code.
-
Using multitools and such on a door with a note now doesn't remove the note. Only grabbing with an empty hand now.
-
-
-
28 September 2018
-
DarkPyrolord updated:
-
-
Fixes a ten year old atmos bug, fix will cause toxins bombs and plasma fires to be a little less lethal
-
Readds modkit sprites to items.dm to fix invis fluff item modkits.
-
-
Farie82 updated:
-
-
No more broken tile due to getting shot out of disposals.
-
Point blank shots not hitting the correct person. When multiple people are on the same tile.
-
-
Kyep updated:
-
-
The wild west away mission no longer offers hijack traitor status as a potential reward.
-
Deconstructing/reconstructing the space pod fab no longer turns it into a mech fab. No more mechanics building surprise mechs.
-
The spacepod fab circuit is now buildable in R&D.
-
Spacepod fabs now require mechanic access to use, like the mechanic R&D console does.
-
-
Purpose updated:
-
-
Mappers can now have Floodlights round-start enabled.
-
-
Tails2091 updated:
-
-
Refactored Hallucinations to match contribution guide standards a bit more.
-
-
Triiodine updated:
-
-
Fixes jade lipstick being lime.
-
Adds lime lipstick.
-
New storage implant icon
-
-
Ty-Omaha updated:
-
-
Ambulances now have sirens!
-
Shadowlings no longer are able to target simple animals (mice)
-
-
farie82 updated:
-
-
fixed cling transformed humanoids looking rather pale.
-
Fixed emagged camera consoles not opening the tabs
-
-
uc_guy updated:
-
-
Vox auto equip the nitrogen tank when spawning if possible.
-
Nitrogen tanks no longer overwrite job items.
-
-
variableundefined updated:
-
-
Benjaminfallout's fluff item.
-
Qdel log is now re-added to the garbage subsystem to enable coders to investigate sources of hard delete.
-
When you remove a light tube while lying down, the light tube disappear. This no longer happens.
-
Latejoin AI no longer spawn in naked at arrival shuttles.
-
Not spawning in with your memory of bank account at roundstart...
-
-
-
27 September 2018
-
Anasari updated:
-
-
You can now deconstruct a fire extinguisher cabinet to yield a single piece of metal. You can construct them for five pieces of metal, with extinguisher included. (Using metal construction menu)
-
-
Birdtalon updated:
-
-
Borg modules now add item action buttons if present.
-
Beepsky responds to attacking him with disarm intent.
-
-
CornMyCob updated:
-
-
Adds in a prompt for becoming a headslug.
-
-
Crazylemon64 updated:
-
-
Adds a fluff item for ELO
-
-
DesolateG updated:
-
-
Added a check to whispering adverbs to prevent double adverbs while whispering.
-
-
FalseIncarnate updated:
-
-
Adds mixing bowls, which allow you to cook multiple recipes at the same time! The dinnerware vendor comes pre-stocked with 10!
-
Adds 2 mixing bowls to the Food Crate from cargo should you need additional. This is the same crate that includes the extra bottle of enzymes.
-
Burned messes now scale their carbon and "????" content with both physical ingredients and directly inserted reagents while burning in the cooking machines.
-
Upgraded cooking machines now attempt to evenly distribute reagents from ingredients across all produced results, rather than just the original.
-
-
Farie82 updated:
-
-
You can remove notes from an airlock now with the grab intent using an empty hand.
-
-
Fox McCloud updated:
-
-
Fixes 128x128 menu location
-
-
Kyep updated:
-
-
Refactored shieldgen.dm, fixed a bug which could cause shieldgens to behave improperly under some rare conditions.
-
-
Purpose updated:
-
-
CPU Performance tweaks in the Bananaium floor honks & squeaks
-
Capitalisation correction in automated chef npcs
-
CPU Performance tweaks in the Xeno Hunter tackles
-
CPU Performance tweaks in Malf AI
-
NT Formal clothing now updates to the station names correctly.
-
Fixes typos in NT Formal clothing
-
Minimap is now updated
-
Holopads now use the correct amount of power.
-
CPU Performance tweaks in the Pipe Dispenser
-
Blobs now delete light fixtures correctly.
-
use_power variable is more clearly defined as non-boolean via defines.
-
-
TDSSS updated:
-
-
Atmospherics external airlocks can now be controlled by borgs and AIs
-
-
Triiodine updated:
-
-
righthand fork sprite being oriented wrong.
-
-
Ty-Omaha updated:
-
-
Fixes vending machine bank account security. You can now use them with a bank account security level above zero.
-
Fixes a bunch of \ tags
-
-
alex-gh updated:
-
-
Drask no longer take damage from cryokinesis
-
Cryokinesis deals less damage, but lowers the body temperature a lot more.
-
Autopsy scanner now prints all times in human readable format.
-
-
datlo updated:
-
-
Added the wizard spell Greater Knock, letting them remove all access restrictions on the Cyberiad and master door opening.
-
-
variableundefined updated:
-
-
drop_location & AllowDrop() has been ported over from tg. Report unexpected issues with dropping items.
-
When you late join, extra items you can't equip / hold spawn on the ground instead of in the lobby screen. Including vox medkit etc.
-
Plasmaman no longer get double the firepower when spawning in as Captain, BS, or sec roles.
-
Non-human's DNA (Except for IPC, of course) should show up properly in the DNA modifier now.
-
-
-
25 September 2018
-
Birdtalon updated:
-
-
Secure console UI (security records) appears bigger by default.
-
One-click-antag now respects game-mode's protected jobs.
-
-
Fox McCloud updated:
-
-
adds support for 128x128 skin interface pixel size for 4K monitors
-
-
Purpose updated:
-
-
Space is now visible under corner pieces of the Intact Empty Ship ruin.
-
-
-
24 September 2018
-
Triiodine, Desolate, updated:
-
-
Things without blood bleeding red when rolled over by a mulebot.
-
-
-
19 September 2018
-
Birdtalon updated:
-
-
Screwdrivers now open fire alarms instead of wirecutters.
-
-
-
18 September 2018
-
Birdtalon updated:
-
-
Laser tag ED-209 bots get the correct names upon construction.
-
-
Ty-Omaha updated:
-
-
adds a missing italics tag to nano/templates/song.tmpl
-
-
-
16 September 2018
-
Shazbot updated:
-
-
Adds in the ability to have multiple custom screens.
-
Adds in Lumi's custom faces.
-
-
dandykong updated:
-
-
Internal manipulation surgeries can now be performed on mouths after the head is augmented.
-
-
variableundefined updated:
-
-
Contribution.md now properly state that changelog is mandated for all PR.
-
-
-
14 September 2018
-
Ty-Omaha updated:
-
-
Fixes logic with obscure proc adjust_bodytemperature
-
-
-
11 September 2018
-
Aurorablade updated:
-
-
Adds a missing var to cult comms logging.
-
-
alex-gh updated:
-
-
It is now possible to heal robotic limbs and IPCs through View Variables
-
-
variableundefined updated:
-
-
pAI can no longer use name with special characters that cause their chat messages to disappear.
-
-
-
09 September 2018
-
AffectedArc07 updated:
-
-
You can no longer gib everyone on the server by forcing admins to call verbs with NTSL
-
-
Agameofscones updated:
-
-
removes the equip region for the mask slot on holobadge-cords
-
changes implementation of https://github.com/ParadiseSS13/Paradise/pull/9471 to be smarter and more long term.
-
-
Kyep updated:
-
-
Fixed bad spawn points in the Wizard Academy away mission.
-
The two welding goggles that went missing from the table in atmos have been returned.
-
-
SkeletalElite updated:
-
-
The paper in the holoparasite kit now describes both of the Chaos holoparasite's modes
-
-
Ty-Omaha updated:
-
-
Nightmare writhing now properly works
-
Fixes the wire under the door in med maint that led to a wall
-
Virology now has a hologram
-
-
nicetoolbox updated:
-
-
Prevent instant rev victory in rev gamemode
-
Cryo now heals all your mutated limbs
-
-
uc_guy updated:
-
-
Ghosts can no longer eject IDs from fax machines and ID computers.
-
Fixed exploit that allowed exiled mobs to return to the station
-
-
variableundefined updated:
-
-
One-click antag vampire showing up as a changeling on antag HUD.
-
Claw game should give you token for payment by card properly again.
-
Mime forcewall now properly last for 30 seconds instead of 10.
-
The cancel button actually work properly when editing memory now.
-
A wallet now shows a green card decal by default if there's a card inside.
-
-
-
05 September 2018
-
IrkallaEpsilon updated:
-
-
Adds an attack cooldown on mirrors for all mobs. Yes simple mobs and Xenomorph larvaes included
-
-
variableundefined updated:
-
-
Economy code has been slightly refactored. Report issues.
-
EFTPOS no longer has a name.
-
All date on transaction log should be in long form like "1 January, 2500 22:00:00".
-
Negative number is represented by parentheses in transaction log, positive without (Opposite of before).
-
There's a higher chance of winning $10 in the slot machine now.
-
-
-
04 September 2018
-
Flatty updated:
-
-
Additional icon scaling settings
-
-
FreeStylaLT updated:
-
-
New Kidan sprites and accessories
-
-
IrkallaEpsilon updated:
-
-
Atmos Grenades wont appear in Surplus anymore due to them virtually being unuseable due to OOC reasons in almost any case.
-
-
Kyep updated:
-
-
The power grid in the black market packers away mission has been fixed, and it is no longer possible to effectively skip the entire mission using a crowbar.
-
Lateround blobs now start off as an infected mouse. By moving around/ventcrawling as a mouse, they can find themselves a good nesting area before they turn into a blob core.
-
Meth (and ultra-lube, its equivalent for synthetics) now grant less of a speed bonus.
-
-
Shazbot updated:
-
-
Now you can actually make xeno borgs.
-
-
TDSSS updated:
-
-
Medbelts can now hold hyposprays.
-
-
Tails2091 updated:
-
-
Double welding a closet no longer removes welding tool. format: Changed 0 1 booleans to TRUE FALSE.
-
-
Ty-Omaha updated:
-
-
Secure fridges can be properly emagged
-
Secure fridges can now be EMP'd to override their access requirements
-
-
datlo updated:
-
-
Megaphone now uses the user's speech font (Wingdings/comic sans)
-
-
nicetoolbox updated:
-
-
Fixes Plasmamen wizards not counting as fully garbed
-
-
variableundefined updated:
-
-
Analyzer are now consistently spelled Analyzer instead of Analyser.
-
Hivelord remains send the proper feedback about its preservation method to database.
-
IPC no longer displays their UI / SE in console. Same goes for other invalid subjects. You also can't save their UI / SE anymore.
-
-
-
31 August 2018
-
variableundefined updated:
-
-
Being incapacitated when changing IPC monitor now show a message properly.
-
Borg & AI say actually work properly now. They no longer become whisper.
-
-
-
30 August 2018
-
Alffd updated:
-
-
Fix emote check of can_speak() to only return if the emote produces sound.
-
-
Kyep updated:
-
-
Fixed depot armory shield key not being properly randomized.
-
-
Ty-Omaha updated:
-
-
Decreases sechailer shitcode
-
-
-
29 August 2018
-
Agameofscones updated:
-
-
Removes stray pixel in RD sechud.
-
-
Flatty updated:
-
-
You can now put items on people and take them off while you're riding that sweet, sweet wheelchair.
-
-
Kyep updated:
-
-
Fixed various bugs with spider structures (webs, cocoons, etc), such as them not triggering attack animations, not respecting melee cooldowns, being invulnerable to simple_animals and aliens, etc.
-
-
Superhats updated:
-
-
Adds Meson and Diagnostic HUD implants.
-
ERT equipment has been reviewed by Nanotrasen and changed to more appropriately assist the station when called.
-
Amber Janitor ERT Armor sprite now works.
-
Field Surgery Belt added for Code Amber Medical ERT
-
-
Triiodine (Agameofscones) updated:
-
-
Removed original paramedic EVA sprites
-
Replaced paramedic EVA sprites with medical hardsuit inspired set.
-
Added species variants _(Which did not exist before hand)_ to Unathi, Tajaran, Drask, Skrells, & Vulpkanins.
-
Added the same armor values the basic EVA suit gets (bio 100, rad 20), this puts the paramedic suit in standard with other NT soft suits. edit: Fixed a typo in the santasuit comment, because why not.
-
-
Ty-Omaha updated:
-
-
NT Rep stamp no longer stamps as Central Command, they have their own stamp now.
-
-
variableundefined updated:
-
-
Cutting wires shouldn't cause a runtime error anymore.
-
You cannot bola people without at least two legs (on them) anymore.
-
-
-
28 August 2018
-
Alffd updated:
-
-
Fixes emote code to preform mute checking in the same manner as say code.
-
Adds a new type of muzzle that will shock its wearer when pulsed by an assembly.
-
Adds a new type of voice trigger assembly that is activated by audible emotes.
-
-
Birdtalon updated:
-
-
Fixes torn down posters dropping hypothetical poster when their wall is deconstructed.
-
-
Flatty updated:
-
-
IPCs can also change their screen color in addition to the image now
-
-
Ty-Omaha updated:
-
-
Harm intent attack animations are red instead of white
-
-
taukausanake updated:
-
-
Corrects formatting for the abductor objective messages
-
-
variableundefined updated:
-
-
Logging for prayer.
-
Silicons no longer broadcast their radio message to everyone in hearing range (Only those next to them). Yes, that's a bug, not a feature.
-
-
-
26 August 2018
-
Agameofscones updated:
-
-
Mr. Chang vendor sprite (icon_state: chang).
-
Three new Mr. Chang vendor slogans.
-
-
-
23 August 2018
-
Aurorablade updated:
-
-
Changes to air Subsystem to make it load faster taken from TG by SpaceManiac.
-
Attemps to cap dogs you can cough up to 10..then you cough up a plush fox. Totally normal.
-
-
Birdtalon updated:
-
-
Fixes unexpected item deletion upon changing species.
-
-
Kyep updated:
-
-
Fixed a few bugs (notably, grid check event raising alert level) in the depot.
-
Fixed hand_tele, bluespace tomatoes, etc not respecting the tele_proof flag of areas.
-
-
alex-gh updated:
-
-
Changeling fleshmend no longer overfills their blood.
-
-
variableundefined updated:
-
-
Admin logging for kinetic accelerator.
-
Implantcase no longer disappears when dropped or placed in bag.
-
Logging to borer infestation.
-
A runtime with admin ticket.
-
Defibrillator paddles snap away if you walk away from the defibrillator.
-
Fixes the discard action not displaying who discarded a card from a hand of card
-
Fixes deck of card not being removed properly from your pocket when you drag it over your sprite.
-
-
-
18 August 2018
-
Crazylemon64 updated:
-
-
makes AA's map fix not annihilate every map PR in existence
-
-
-
16 August 2018
-
AffectedArc07 updated:
-
-
Half the scrubbers actually work now
-
-
Birdtalon updated:
-
-
All obj/machinery is now below obj layer.
-
Prevents creation of 0u pills with Chem Master
-
-
-
15 August 2018
-
tlc2013 updated:
-
-
The AutoDrobe now carries a Transylvanian Coat, imported straight from /vg/station for all your Dracula-cosplaying needs. Much like the false Wizard robes, it does nothing for the actual antagonist.
-
-
variableundefined updated:
-
-
Banangarang's medical fluff cyborg's hair colour inconsistency.
-
Comfrey now actually works for healing brute damage.
-
-
-
09 August 2018
-
variableundefined updated:
-
-
banangarang's maid bot fluff sprites
-
-
-
07 August 2018
-
Anasari updated:
-
-
Polaris card system partially ported. Credits to Jedr for the hand of card item_action sprites.
-
-
Kyep updated:
-
-
Simple_animal mobs now get a HUD button that lets them switch between HELP and HARM intents.
-
Replaced the Syndicate Supply Depot with a new version, rebuilt from scratch, that is much more challenging/interesting.
-
It is no longer possible to walk straight through decoy AI cores as if they were not there.
-
Syndicate grenade launcher turrets now actually launch grenades.
-
-
MarsM0nd updated:
-
-
Unathi can now tailwhip when they are supposed to be able to.
-
Tail whipping gets logged.
-
-
-
06 August 2018
-
AffectedArc07 updated:
-
-
Barber no longer spawns with an extra pair of shoes in his bag
-
-
Tails2091 updated:
-
-
Fixed Therapy Dolls not working.
-
Made Prize Machine & Merch Sore readable.
-
Fixed capitalizations and typos in both lists.
-
-
-
05 August 2018
-
Crazylemon64 updated:
-
-
Space ruins can no longer trap you upon border transition
-
There are now several levels of space ruins
-
-
Fox McCloud updated:
-
-
Adds in medical hyposprays
-
-
-
03 August 2018
-
Fox McCloud updated:
-
-
IPC Change monitor is now an action button
-
Slime Color change is now an action button
-
Fixes staff of change leaving behind unknowns
-
Fixes Shadowlings not having shock resistant and thermal vision
-
Fixes staff of change gibbing people
-
-
Shazbot updated:
-
-
Adds in the ability to unsaw sawn off riot shotguns. Change: Changes the riot shotgun icon.
-
-
-
02 August 2018
-
variableundefined updated:
-
-
Nightmares now works. Sleep well.
-
Megaphone actually logs in say log now.
-
-
-
01 August 2018
-
Citinited updated:
-
-
Heaters and freezers now have min and max buttons
-
-
CornMyCob updated:
-
-
The description for miniature energy guns is now accurate
-
The third person text of someone reinforcing an airlock is now accurate
-
-
Tails2091 updated:
-
-
Karma refund now uses switch statement.
-
-
datlo updated:
-
-
Updated syndicate hardsuit description.
-
-
-
31 July 2018
-
Tails2091 updated:
-
-
Claw Game Prize Ball now drops more than one ticket like it should.
-
-
variableundefined updated:
-
-
fix a runtime error with bluespace projector
-
-
-
30 July 2018
-
Tails2091 updated:
-
-
Changed wannabe for loop to a real for loop.
-
-
-
28 July 2018
-
KasparoVy updated:
-
-
You can now safely augment the heads of pointy-snooted Unathi, although your mileage may vary.
-
-
-
27 July 2018
-
AffectedArc07 updated:
-
-
You can no longer use embeds in NTSL
-
-
Crazylemon64 updated:
-
-
Space hotel is back in business
-
Non-hotel SNPCs work again
-
-
Fox McCloud updated:
-
-
Extract posibrains should have the correct names now
-
Abductors can now purchase a mind device to speak into crewmembers minds or give directives to abductees
-
Abductors now have their own versions of the FixOVein, Bonesetter, and Bonegel. Credit to Triiodine for the sprites
-
Adds a new electric shock and chemical gland for abductors
-
viral gland generates random viruses and egg laying gland eggs now have random reagents in them
-
-
variableundefined updated:
-
-
Cyborg Analyzer no longer rounds off the damage number it displays.
-
-
-
25 July 2018
-
variableundefined updated:
-
-
Fixes runtime error from medical kit change
-
-
-
24 July 2018
-
Kyep updated:
-
-
Number of roundstart atmos suits in atmos increased from 2 to 4.
-
-
-
22 July 2018
-
Fox McCloud updated:
-
-
Fixes monkeys not having their own HUD
-
Fixes monkey to human transformations missing their HUD
-
Fixes changing species unequipping items
-
Fixes organs not being rejuvinated properly by mitocholide
-
Fixes shadowlings not being forced to hatch
-
Having a robotic head will allow you to use buzz, ping, beep, and the likes
-
Claw sharpening now works
-
Abductors have their own headset instead of a syndicate one
-
Can put monkeys in the gibber
-
gibbing some species will now generate different types of hides (monkeys give monkey hides, unathi give lizard hides, the likes)
-
fixes Vox name generation based on the wrong syllables
-
consolidates diona name lists; you'll no longer be asked to rename your Diona when you start the shift
-
botany grown diona can no longer rename themselves (as is consistent with ghost roles)
-
Fixes DNA scrambler so it gives a proper randomized species name
-
Fixed an edge case were Vox would have a permanent nitrogen alert
-
Fixes operatives being bald most of the time
-
Adds beesplosion chemical reaction
-
-
and taukausanake updated:
-
-
Swarmers can no longer destroy active clone pods.
-
-
-
17 July 2018
-
Citinited updated:
-
-
volume pumps can be dispensed by the RPD again
-
-
datlo updated:
-
-
Provided abductors with an infection free surgery table.
-
-
-
16 July 2018
-
Citinited updated:
-
-
RPD behaviour has been slightly tweaked - for example you can now rotate / flip / delete individual pipes by clicking on them without affecting other pipes on that tile.
-
-
Fox McCloud updated:
-
-
Fixes hand labelers not being able to label storage objects
-
Cameras can now be destroyed with weapons that have a force of 12 or greater
-
Cameras have 2 wires as opposed to 6; camera focus and power wires still remain
-
You can use hand labelers on reagent containers now
-
-
-
14 July 2018
-
Anasari updated:
-
-
Assuming there is heal left, bandages and ointments used on limbs now heal both the limb and the hand / foot. Bandages and ointments used on the torso now heal head, arms, and lower body. The one on lower body heals the legs too.
-
-
Aurorablade updated:
-
-
Adds Spess Koi and related event.
-
-
Citinited updated:
-
-
The tachyon-doppler array now has a logging interface, and can print off stored explosive logs. Brag to your friends about your bomb-making skills!
-
-
Fox McCloud updated:
-
-
Robotic brains have their own unique sprite and full flavortext's now
-
Fixed a bug where IRC's would have IPC names
-
-
-
11 July 2018
-
Alffd updated:
-
-
Updates SM engine to modern standards
-
Ports SM monitoring system from Bay and TG
-
Adds station wide radiation alarm when crystal/shard goes critical
-
Tesla zapping
-
-
Citinited updated:
-
-
Fortune cookies now drop random fortunes if cooked with a blank piece of paper.
-
-
Fox McCloud updated:
-
-
Adds constructable Integrated Robotic Chassis
-
Adds surgery to customize existing robotic limb appearances
-
Positronic brains renamed to robotic brains
-
-
FreeStylaLT updated:
-
-
Added a Harmonica to Perma Brig
-
-
datlo updated:
-
-
Replaced instances of "Human" in ion laws by "Crew".
-
Fixed the ability of Service Borgs to spawn items on floors. Dosh!
-
-
-
10 July 2018
-
Fox McCloud updated:
-
-
Can no longer take assisted organs at round-start (mechanical organs are still a go, but renamed to cybernetic organs)
-
Can now start the round with cybernetic lungs, liver, and kidneys
-
Can produce cybernetic eyes at R&D and mechfabs
-
Cybernetic internal organs no longer take reduced damage (this does not apply to augments)
-
Cybernetic internal organs can be rendered inoperable (this does not apply to augments)
-
Fixes mitocholide/oculine healing damage on cybernetic organs
-
Fixes being able to restart a dead heart in your hands or with a defib
-
-
-
09 July 2018
-
Fox McCloud updated:
-
-
Enabled augmentation of the head
-
Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; also adds cybernetic upgraded lungs
-
Heads are no longer vital organs, but brains still are
-
-
-
07 July 2018
-
Fox McCloud updated:
-
-
Stechkin pistols in maintenance no longer spawn with a broken magazine
-
-
Kyep updated:
-
-
Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, still exist.
-
-
-
06 July 2018
-
Fox McCloud updated:
-
-
removes explosive lances
-
-
datlo updated:
-
-
Replaced duplicate labor shuttle console on the bridge by a mining shuttle console.
-
-
-
04 July 2018
-
Citinited updated:
-
-
Spelling error in agent IDs
-
-
-
03 July 2018
-
MINIMAN10000 updated:
-
-
Restrained spacepod passanger can now exit pending a 2 minute wait time without moving.
-
-
-
02 July 2018
-
Citinited updated:
-
-
Canisters obey melee cooldown now
-
-
Crazylemon64 updated:
-
-
All MMI variants can now install an "MMI radio upgrade" in order to acquire radio capability when outside of any other chassis. It can be installed either directly on the MMI, or through an opened cyborg chassis. This radio can later be removed if desired by using a screwdriver on the MMI.
-
MMIs can now pull up the direct interface of the radio instead of a single-toggle verb
-
MMI radio control is now done via action button instead of via verb
-
The radio MMI no longer exists as a distinct item
-
-
-
01 July 2018
-
Anasari updated:
-
-
Shuttle can be called at 30:00 instead of 25:00 during War Ops.
-
-
Citinited updated:
-
-
The chef can now process spaghetti into macaroni, and can make several derivative foodstuffs.
-
-
datlo updated:
-
-
Syndicate clowns can now purchase Clown Magboots. Keep honking through slips and atmos!
-
-
monster860 updated:
-
-
Adds the mining podbay (again)
-
-
-
30 June 2018
-
Citinited updated:
-
-
Adds the conveyor belt placer and bluespace conveyor belt placer, allowing you to much more easily create conveyor belts. The former can be gotten at any autolathe, the latter must be researched first.
-
Use a conveyor belt lever on aforementioned item to link all belts inside the placer with that lever.
-
-
-
27 June 2018
-
MINIMAN10000 updated:
-
-
Containment emitters
-
deferred processing of SMES
-
-
-
26 June 2018
-
Alffd updated:
-
-
Additional logic to atmos throwing.
-
-
-
23 June 2018
-
matt81093 updated:
-
-
death squid hitbox position
-
-
-
19 June 2018
-
Anasari updated:
-
-
Gloves of the north star is now categorized under highly visible and dangerous weapon instead of pointless badassery. (Because it's actually good)
-
-
Fox McCloud updated:
-
-
Can cast spells on CentComm z-level during ragin' mages
-
-
MINIMAN10000 updated:
-
-
Cardboard drop counts
-
-
-
17 June 2018
-
Fox McCloud updated:
-
-
Fixes wizards not spawning with their clothes and backpack
-
It no longer snows on away missions
-
-
variableundefined updated:
-
-
Nuclear challenge time limit now depends on round start time.
-
-
-
13 June 2018
-
Aurorablade updated:
-
-
Fluff for Panzerskull
-
-
Fox McCloud updated:
-
-
Medibots now actually talk, like beepsky
-
Adds Plastic surgery; fix someone's face or give them a new identity!
-
Having more than 50 cloneloss will render you "Unknown"
-
head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
-
Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
-
Fixes syndicate medibot not being constructable from tactical medkits
-
Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
-
Radiation event reworked; graphics updated--effects may be a bit more deadly
-
Buffed DIY chainsaws damage slightly
-
You now flip about when you spin with a double e-sword
-
Adds surgical augment to R&D
-
Tools on surgical augment are slightly faster at surgery
-
Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
-
Toxin damage is stealthier and will no longer cause stinging spam message
-
-
Kyep updated:
-
-
Additional job slots are now available at 80+ server population.
-
-
MINIMAN10000 updated:
-
-
Airlock electronics lock
-
Airlock electronics close button
-
-
Piccione updated:
-
-
Added Magboots to the Paramedic's EVA gear closet
-
-
Tayyyyyyy updated:
-
-
Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
-
-
-
11 June 2018
-
FalseIncarnate updated:
-
-
Food on utensils now properly inherits the name of the source dish.
-
Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
-
-
-
09 June 2018
-
Fox McCloud updated:
-
-
Fixes holobarrier icons being missing
-
-
-
08 June 2018
-
Alffd updated:
-
-
Adds an automated emergency var on air alarms for mappers
-
-
Anasari updated:
-
-
Fixes admin log for spray displaying (0,0,0) all the time.
-
-
Desolate updated:
-
-
ED-209 code corrected to work properly. Floorbot code corrected to work properly.
-
-
and Dumbdumb updated:
-
-
Unathi and Vox Sec Hardsuit update
-
-
-
05 June 2018
-
Kyep updated:
-
-
The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe.
-
-
-
04 June 2018
-
Fox McCloud updated:
-
-
Hulk mutation no longer works at range (ie: punching/breaking windows/walls at range)
-
You must be on harm intent to damage things if you have hulk
-
Having hulk allows you to punch and damage just about anything
-
-
uraniummeltdown updated:
-
-
You can smelt titanium and glass together to form titanium glass for building shuttle windows
-
You can smelt titanium, plasma and glass together to form plastitanium glass for building plastitanium windows
-
Fulltile windows now smooth, windows crack as they get damaged and can be repaired with help intent welder
-
Windows have deconstruction hints and show whether they can be rotated or not
-
Plasma glass no longer gets auto-colored
-
RCDs can deconstruct airlocks again, they have no force now though
-
Wielded fireaxe does a lot of damage to windows and grilles instead of just deleting them
-
Glass stacks now use stack recipes instead of a custom menu
-
-
-
31 May 2018
-
FalseIncarnate updated:
-
-
The singulo no longer feeds on attention.
-
-
-
26 May 2018
-
Birdtalon updated:
-
-
Holoparasite guide updated to include newer models. Small tooltip added for charger models.
-
laser tag gun projectiles now play appropriate sound when striking.
-
-
Citinited updated:
-
-
Hopefully fixes all issues with disposals sending you to nullspace.
-
-
Fox McCloud updated:
-
-
Fixes not being able to propel yourself through space by farting if you possessed both superfart and toxic farts
-
-
Kyep and Bxil updated:
-
-
Prevents everyone and their mother from seeing through closed poddoors.
-
-
Tayyyyyyy updated:
-
-
Most things will now use the correct pronouns.
-
Newscasters properly check for feed channel creation and wanted issue creation
-
ERT should deploy properly without admins now.
-
-
-
19 May 2018
-
Aurorablade updated:
-
-
Vet Coat Fluff item.
-
Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling error).
-
-
Fox McCloud updated:
-
-
Adds gloves of the North Star; get them on the uplink for 8 TC
-
Unarmed attacks now have their own icons, as does disarming.
-
Various mobs have their own custom icon attacks
-
Monkies now bite!
-
-
-
18 May 2018
-
Fox McCloud updated:
-
-
Removes engineering and police tape
-
Adds security, atmospheric, and engineering holoprojectors
-
-
tigercat2000 updated:
-
-
You can now lock a facing direction with shift+middle mouse button, or lock your direction towards an object by clicking on it with shift + ctrl + middle mouse button.
-
-
-
15 May 2018
-
Tayyyyyyy updated:
-
-
Pun pun is back!
-
-
-
11 May 2018
-
Kyep updated:
-
-
It is no longer possible to create an infinite number of monkeys from the same monkey cube.
-
-
-
09 May 2018
-
RyanSmake updated:
-
-
You can now jump on fax machines without the UI lying to you.
-
-
-
07 May 2018
-
qwertyquerty updated:
-
-
The window title is custom now!
-
-
-
06 May 2018
-
Kyep updated:
-
-
DeathSquad is now better equipped, and prompts eligible ghosts with a "Do you want to play as DeathSquad?" when called.
-
DeathSquad members (except team leaders) can now choose to spawn as either an organic DS member, or a DS borg.
-
-
-
05 May 2018
-
Tayyyyyyy updated:
-
-
ERT members will have their proper name and appearance when cloned
-
-
-
04 May 2018
-
RyanSmake updated:
-
-
You will now log in to the proper account you input to the ATM instead of the one associated with you.
-
Now ATMs will reconnect after a power outage.
-
-
-
02 May 2018
-
CrazyLemon and Fox McCloud updated:
-
-
Fixes reagent smoke
-
-
-
01 May 2018
-
Alffd updated:
-
-
Tell clients to rejoin after shutdown, before killing the server.
-
-
Fox McCloud updated:
-
-
Removed programmable unloader circuit
-
Bomb testing range can now be utilized multiple times without worry of the bomb bouncing off and returning back to you
-
-
-
30 April 2018
-
Fox McCloud updated:
-
-
Adds Guillotines: make them with plasteel, wood, and cable coil. Execute your comdom head of staff TODAY
-
Clapping now actually plays a clapping sound
-
Adds Blast cannon
-
-
FreeStylaLT updated:
-
-
Medbay treatment center now has a wider entrance
-
Virology hallway is now publically accessible from Surgery waiting room, entrance is now double-doors.
-
-
-
28 April 2018
-
MINIMAN10000 updated:
-
-
Developer express start
-
-
-
26 April 2018
-
Fox McCloud updated:
-
-
Destroys uplink metagaming: Adds in F.R.A.M.E. cartridge
-
using raw telecrystal on an active uplink or yourself will use the entire stack at once
-
can purchase 5 and 20 unit TC bundles from the uplink
-
Removes radio icons when speaking over radio
-
Fixes cargo recycler never recycling items on its own
-
Fixes mech fabricator using an all white UI
-
Can upload alien alloy design to the ORM
-
-
Tayyyyyyy updated:
-
-
You only need to click once to clean a floor
-
-
uraniummeltdown updated:
-
-
Slimes can be injected with plasma reagent and epinephrine to control mutation chance. Plasma increases mutation chance 5% per 5u to a max of 50%, epinephrine decreases by 5% per 5u to a minimum of 0%
-
Slimes can change their face using new emotes
-
Slimes can steal nutrition from other slimes when attacking them
-
Slime docility potion no longer makes a simple animal slime, instead makes the target docile and never hungry
-
-
-
25 April 2018
-
Fox McCloud updated:
-
-
Can make water bottles and caution signs out of plastic sheets
-
Increased cargo plastic sheet count to 50 and reduced cost to 10
-
Adds a recipe for making plastic sheets: oil, acid, and ash
-
Can now make a designs on the circuit imprinter that use metal and other exotic materials
-
Removed the acid cost from most circuit recipes
-
bluespace material requirement on a few parts: bluespace stock parts, phazon parts, bags of holding, and the likes all now require bluespace lattice.
-
Fixes invisible plushies and getting fluff item plushies
-
-
Tayyyyyyy updated:
-
-
You can't see admin character names in PMs
-
-
Xhuis updated:
-
-
The Nanotrasen Meteorology Division has identified the aurora caelus in your sector. If you are lucky, you may get a chance to witness it with your own eyes.
-
-
-
24 April 2018
-
Kluys updated:
-
-
Cleanblots not cleaning /obj/effect/decal/cleanable/trail_holder (blood trails)
-
-
-
17 April 2018
-
Citinited updated:
-
-
Kitchen machinery no longer looks as if it is falling apart.
-
-
MINIMAN10000 updated:
-
-
Adds NOBLUDGEON to door_remote so the remote always triggers
-
Cable coils now allow you to transfer a part of the stack
-
Stack handling from cable.dm is removed as stack.dm already handles it
-
Changed cable coil message
-
The ability to change the color of cables
-
cableColor now follows the new cable_color format
-
-
-
14 April 2018
-
Anticept updated:
-
-
Changed defib timer from 3 minutes to 5 minutes
-
-
MarsM0nd updated:
-
-
Single man up now looks and sounds the same as the global man up for that person.
-
-
-
11 April 2018
-
KasparoVy updated:
-
-
Removes the job-restriction on the purely cosmetic Tajaran veils while those wth integrated HUDs remain unchanged.
-
-
-
08 April 2018
-
Kyep updated:
-
-
Terror Spiders now have a new type in their roster (brown) and see the health status of humanoids (since some of their abilities depend on that status). The Terror Spider away mission has also been adjusted to smooth out areas of no challenge (safe spaces) as well as areas of nigh-impossible challenge (dozens of spiders stacking up together in the final room).
-
-
-
07 April 2018
-
Alffd updated:
-
-
portable (stationary) scrubbers now remove 1/4th as much air per tick at maximum.
-
-
Birdtalon updated:
-
-
Nanocalcium can no longer be synthesised by bees or Odysseus
-
Silicons now have their diagnostic HUD removed correctly.
-
Defibs no longer give endless paddles.
-
Ether re-balanced into a more effective anaesthetic for surgery.
-
Atmos techs have access to tech storage and inner engineering tool room.
-
-
Citinited updated:
-
-
You can't play russian roulette without a head
-
using a russian revolver on another human will now hit them with the revolver instead of failing to play russian roulette with them.
-
-
Crazylemon64 updated:
-
-
Deletion of human mobs now properly deletes equipment balance: Hotel guards now dust on death balance: Hotel guards no longer drop equipment when stunned balance: Hotel guards now are able to use the tasers they hold
-
-
Dyhr updated:
-
-
Agent ID's now provide some presets for valid occupations.
-
-
Kyep updated:
-
-
SIT shuttle can no longer dock in scimaint.
-
Crew demotions and terminations now generate an automatic message to admins. All job changes are also logged.
-
Modular computers now support toggling priority on/off for jobs. The button for doing this in both normal and modular computers is now marked 'Pri', instead of the old '*'.
-
-
MarsM0nd updated:
-
-
Admins can make a fax machine recive the faxes Centcomm or the Syndicate does get.
-
Stops "Unknown" department to send to from coming up when a fax machine gets spawned.
-
Allows adding of departments to send to over a proc-call.
-
-
Spacemanspark updated:
-
-
Mining drones now have movement sprites.
-
-
uraniummeltdown updated:
-
-
Drones will no longer shatter glass tables
-
All small mobs can bump open public access doors
-
-
-
06 April 2018
-
Fox McCloud updated:
-
-
Fixes medical cyborgs having one less stack than they should have they recharge
-
Fixes inconsistency in the medical stacks amounts (they should all be 6)
-
-
-
05 April 2018
-
uraniummeltdown updated:
-
-
Aliens can pull facehuggers out of eggs again
-
-
-
03 April 2018
-
& Deathride58 & Tigercat2000 updated:
-
-
Station time is now randomized [if enabled in game_options configuration].
-
A separate round time has been added to status panel. This will start at 00:00:00.
-
Night shift lighting [if enabled in the same configuration] will activate between station time 7:30 PM and 7:30 AM. This will dim all lights affected, but they will still have the same range.
-
APCs now have an option to set night lighting mode on or off, regardless of time.
-
-
-
02 April 2018
-
Desolate updated:
-
-
New Cricket Borg module selection.
-
-
EldritchSigma updated:
-
-
Mech mounted Disablers are now printable with consistency.
-
-
Fethas updated:
-
-
Viruses Lycancoughy, Adv. Pierrots throat and Kingstons added.
-
-
IK3I updated:
-
-
You can now opt out of the syndicate recruitment semminar prior to boarding the station.
-
-
Kyep updated:
-
-
Syndifox and Syndicat can now do melee damage. Paperwork (cargo sloth pet) no longer can.
-
Syndifox and Syndicat are no longer controllable by players by default.
-
Poly (parrot in Engineering) now knows more phrases.
-
-
Shazbot updated:
-
-
Adds E-pistol crates to the cargo manifest Change: changes the HoP's E-gun to an E-pistol
-
-
Tayyyyyyy updated:
-
-
Borg power warning is on a 2 second cooldown
-
-
-
01 April 2018
-
Tayyyyyyy, LP Spartan updated:
-
-
Once you up to red, it takes 5 minutes before the shuttle transit time is reduced to 5 minutes.
-
-
-
30 March 2018
-
matt81093 updated:
-
-
fish duplication when pulling out multiple fish at once
-
-
-
28 March 2018
-
Birdtalon updated:
-
-
Enforces size limits for placing items inside slicable food
-
-
Fox McCloud updated:
-
-
Nano UI will update a bit faster
-
-
MarsM0nd updated:
-
-
Record printouts now automatically get labled with the name of the person.
-
-
-
25 March 2018
-
Alffd updated:
-
-
Logic checks to lessen death from flying objects due to atmospheric breaches.
-
Removes atmospheric stunning while thrown.
-
-
-
24 March 2018
-
matt81093 updated:
-
-
Borgs no longer keep their special vision when reset with the reset module
-
-
uraniummeltdown updated:
-
-
Deconstructing default RCD airlocks should work now
-
-
-
22 March 2018
-
uraniummeltdown updated:
-
-
Airlocks now have security levels. Secure airlocks cannot be hacked straightaway. Vault doors and highsecurity airlocks have some security by default. You can make an airlock secure by applying metal and plasteel to it while the panel is open
-
As a slime, you can drag yourself onto a target to feed
-
Doors, tables and table frames can be destroyed by hitting them. Airlocks can be repaired by a welder on help intent.
-
You can butcher with any sharp item on harm intent
-
Grilles are stronger
-
Vault door assemblies cost 8 plasteel up from 6
-
Xenomorphs can open non-locked non-welded airlocks after some time
-
Firelocks can be welded open again, firelock [de]construction uses crowbar instead of welder
-
-
-
21 March 2018
-
MarsM0nd updated:
-
-
Xray machines now have xray vision, and check contents of an item, instead of just the item.
-
-
-
20 March 2018
-
MarsM0nd updated:
-
-
Stops a mug from being invisible
-
-
-
19 March 2018
-
Birdtalon updated:
-
-
re-adds the inline "take" shortcut for adminhelps
-
-
Birdtalon, LPSpartan, Shazbot updated:
-
-
Nanocalcium - bone repair reagent. Adds bone repair kit to syndicate uplink containing Nanocalcium autoinjector.
-
-
Fethas updated:
-
-
Vulpkanin, Hunger drain increased slightly. rscadd:Diona now have hair by skittles.
-
Bedsheets can contribute to dream messages.
-
sometimes dreams will be nightmares.
-
Moves dream/nightmare strings to txt files. rscadd:sleeping has a small change to heal brute/fire. but you need a bed..and a bed sheet to be effective.
-
-
Fox McCloud updated:
-
-
Fixes Vulpkanin hunger drain rate being absurd
-
-
IK3I updated:
-
-
Comically sized mugs are slightly less comically sized
-
Lord Singuloth's wrath can no longer be bypassed by baking your input device.
-
-
Shazbot updated:
-
-
Adds an ammo counter to the icon and the in hand icon for the M90-gl
-
Lowers the price of the .357 for nukies
-
-
-
16 March 2018
-
MarsM0nd updated:
-
-
You can now fix broken message monitors
-
-
-
13 March 2018
-
Citinited updated:
-
-
Restricts RPD usage to certain station-side turfs.
-
-
Piccione updated:
-
-
Added marijuana cigarette packets to the Psych's locker.
-
Changed the taste message of a few food items
-
-
-
12 March 2018
-
Fethas updated:
-
-
Full of skittles borg fluff
-
-
-
08 March 2018
-
shazbot updated:
-
-
Fixes up Desolate's name on his other items.
-
-
-
06 March 2018
-
Regen updated:
-
-
Removes the purple hair flower pin from loadout and general player access, because this is a fluff item.
-
-
-
04 March 2018
-
Funce updated:
-
-
APC Interface lock UI works for silicons.
-
-
-
03 March 2018
-
Birdtalon updated:
-
-
A few more items in the Psyche locker.
-
-
Citinited updated:
-
-
IPCs can now lose russian roulette without going to nullspace
-
-
DarkPyrolord updated:
-
-
Sliceable food items are no longer hammerspace capable
-
-
FalseIncarnate updated:
-
-
Adds colored, departmental, and novelty mugs to the hot drinks machine and loadout menu under "Mugs".
-
Adds Head of Staff coffee mugs to their respective lockers.
-
Adds support for inserting items into vendors and having the vendor interact with said item when vending items.
-
Adds the ability to insert containers into the hot drink machine, filling the container with your purchase.
-
-
Fethas updated:
-
-
The booze o' mat now has wine..bags.
-
-
KasparoVy updated:
-
-
The eyes of humanoids who have XRAY vision mutation, sufficiently high darkview, synthetic eyes or eye implants now appear to shine in the dark.
-
Adds a way to 'cut' one icon's pixels out of another by using the get_icon_difference() proc.
-
get_location_accessible() now checks the appropriate flags when determining the accessibility of eyes.
-
-
Serket updated:
-
-
Death Wand can kill slimes and hopefully everything
-
Wizards can no longer mind-swap borgs
-
ERT Specops Office now comes with extra privacy (borgs can't open the ERT mech room, etc.)
-
Removed snow from Mr Chang's
-
Fixed a dethralling error causing message typos
-
-
Tayyyyyyy updated:
-
-
AIs can view info of their synced borgs in the status panel
-
-
-
26 February 2018
-
Birdtalon updated:
-
-
Removes printing photos on security consoles.
-
-
-
21 February 2018
-
uraniummeltdown updated:
-
-
Added titanium and plastitanium. Mine the asteroid for titanium, make plastitanium by smelting together titanium and plasma
-
You can build shuttle floors and walls with titanium and plastitanium. Can also make shuttle airlocks by applying titanium to a non-mineral airlock
-
Shuttle windows have explosion resistance now
-
A few RnD recipes require titanium now
-
-
-
20 February 2018
-
Alffd updated:
-
-
Reduce all atmospheric stuns by 80%
-
Cap the maximum atmospheric stun time to 4 seconds
-
-
Anasari updated:
-
-
Add paperplane. Alt-click or use a verb on a piece of paper in your hand to make them.
-
-
Birdtalon updated:
-
-
adds [time] tag for paperwork
-
-
Citinited updated:
-
-
You can now roll up flags.
-
-
Fox McCloud updated:
-
-
Adds in a Dance Machine
-
IEDs now have a blast radius again
-
Slap crafting of IEDs is gone; use personal crafting instead
-
-
HugoLuman updated:
-
-
coughing and sneezing sounds for the Drask
-
-
MarcellusPye updated:
-
-
Grays can now drink sulphuric acid without being burnt
-
-
Shazbot updated:
-
-
Fixes Patch's patch
-
-
Tayyyyyyy, bryanayalalugo updated:
-
-
News reporters can now add titles to their stories!
-
-
-
05 February 2018
-
IK3I updated:
-
-
Next gen dining is now available at your local autolathe!
-
-
MarsM0nd updated:
-
-
Pod lock busters can now unlock pods
-
Pods can only be locked with a locking system installed.
-
-
Tayyyyyyy updated:
-
-
Energy swords, energy daggers, energy cutlasses, and energy axes emit light. Toy versions do not.
-
-
uraniummeltdown updated:
-
-
Multitile airlock opening/closing animation is no longer glitchy and paper/photos don't float in the air when opening/closing them
-
-
-
02 February 2018
-
Fethas updated:
-
-
TG Port, ais now have an advanced diagnostic hud that lets them see the path a bot is taking.
-
Bots get access for 60 seconds to all doors to get to thier locations. rscadd:Pai controlled bots will get a notification they are being called. rscadd:all living mobs now can have a med hud.
-
-
-
01 February 2018
-
Squirgenheimer updated:
-
-
Using the 'tear reality' rune as cult should now be punished when the invokers do not have the god summoning objective
-
-
Tayyyyyyy updated:
-
-
Players job banned from syndicate can no longer play emagged drones
-
-
uraniummeltdown updated:
-
-
Examining an airlock assembly gives construction hints and shows what pen name is set. Mineral airlocks can have glass added to them.
-
Added public and external maintenance airlock assemblies to metal recipes
-
Maintenance, standard and external airlocks now have glass versions. Multi-tile airlock has a solid version.
-
Added more airlocks to RCD
-
You can attach paper and photos to airlocks, wirecutters to remove them
-
Airlocks open faster
-
Vault and high-security airlocks are made with 6 plasteel up from 4
-
Plasteel should have the correct amount of materials in it now
-
-
-
29 January 2018
-
Fox McCloud updated:
-
-
Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area
-
-
MarcellusPye updated:
-
-
Changes the ghost preferences section of game preferences to display the currently active option instead of the inactive option.
-
-
-
27 January 2018
-
IK3I updated:
-
-
Saving a chat log no longer hangs you.
-
-
uraniummeltdown updated:
-
-
Client FPS setting should save properly now
-
-
-
26 January 2018
-
tigercat2000 updated:
-
-
Insta-movement works marginally better
-
-
uraniummeltdown updated:
-
-
You can now change your client FPS in Game Preferences
-
-
-
24 January 2018
-
IK3I updated:
-
-
Cancel means Cancel on admeme console reports!
-
When eldritch gods, demons, handsy aliens, and incarnations of darkness tell you it's time to go, you go
-
Comms Console will tell you when the shuttle can't be recalled
-
Admemes can now designate whether a shuttle they call is recallable
-
Admemes can exercise their power to recall any shuttle, even in defiance of spooky ghosts!
-
-
Kyep updated:
-
-
Added config option to limit the amount of time shadowlings can remain unhatched before they start getting pushed to hatch.
-
-
Tayyyyyyy updated:
-
-
Energy beams of all types emit light.
-
Flashbangs emit a burst of light when detonated
-
-
-
21 January 2018
-
KasparoVy updated:
-
-
Avoids wanton bloodshed by revising logic that checks for blood already in the splat zone.
-
Adds a helper proc with which you can get a list of all atoms of a type at a given location.
-
-
Tayyyyyyy updated:
-
-
Due to increasing amounts of spaghetti code in the cryptographic sequencer, emagging maintenance drones cripples their table pathfinding and removes their ability to pathfind under people's legs. Also, Nanotrasen has patched its drones to remove the hidden diamond drill module and rewritten its drone control code so that drones that don't call home and verify their programming after a certain amount of time are destroyed automatically.
-
-
-
20 January 2018
-
uraniummeltdown updated:
-
-
Fixed issues with ethereal jaunt directions, wraith jaunt no longer shows the wizard effects
-
Guardians phasing in/out will properly show a little animation
-
The petting heart animation is smoother
-
-
-
19 January 2018
-
Citinited updated:
-
-
Using a syndicate balloon while it's in your hand allows you to play with it.
-
-
uraniummeltdown updated:
-
-
Wooden holodeck table sprites show up properly
-
Table construction has been changed a bit, apply stack items (carpet, metal, glass, wood) to table frames to build tables instead of using table parts.
-
Slightly increased the health of racks and tables with low health
-
Holodeck tables will now smooth with one another
-
Holodeck tables and racks can be interacted with in more ways
-
-
-
13 January 2018
-
Citinited updated:
-
-
The ocean and the pool are no longer colder than outer space.
-
Water now cools or heats you gradually, not all at once.
-
-
Kyep updated:
-
-
Refactored Paranormal/Janitor dress code, and Cyborg ERT spawn code.
-
Signing up for ERT, then going AFK, such that your AFKness prevents you and/or others spawning as ERT within a reasonable (2 minute) period of time, now generates a warning to online admins.
-
-
-
11 January 2018
-
Bxil updated:
-
-
Economy accounts now use the correct date.
-
-
Citinited updated:
-
-
Jaunters work again.
-
-
Jountax updated:
-
-
Fancy shoes no longer cost one's entire loadout.
-
Sugarcane added to the MegaSeed Servitor. No more garden raids!
-
-
Kyep updated:
-
-
Department management (aka: demotion) consoles only worked for their respective head of staff. Captains, CC characters, etc could not use them.
-
Fixed two brown wooden doors in wizard academy away mission which had space turfs under them, leading to nasty results with fastmos.
-
Added deathsquid.
-
Further modified construction site layout, fixing various issues and making it easier to test new engine setups there.
-
-
Tayyyyyyy, FPK updated:
-
-
The more dark view you have, the more eye damage you take from flashing. Darkness amplifies this effect.
-
-
uraniummeltdown updated:
-
-
Freezers and other atmos machines will drop frame and parts correctly again
-
-
-
07 January 2018
-
Kyep updated:
-
-
All mineral floor tiles no longer incorrectly show up as abductor flooring.
-
-
-
05 January 2018
-
Kyep updated:
-
-
Improved wild west away mission. Fixes issues such as lack of magboots, and 'projectile gun's appearing. Adds some flavor items (syndie soap in shower, medkits in storage). Also adds syndie comms device which alters the mission depending on how it is used.
-
-
uraniummeltdown updated:
-
-
Construct shells have a new sprite
-
-
-
04 January 2018
-
Anasari updated:
-
-
A lot of underused nuke op items made cheaper.
-
Syndicate hardsuit removed from nuke op because you already got one free.
-
Tactical medkit give you four synthflesh patch, no more stetho or lethal syringe.
-
RSG added to nuke op uplink. Dart gun no longer available.
-
-
-
31 December 2017
-
Alffd updated:
-
-
Wire panels are now effected by the colorblindness disability
-
Wire panel color changes now support RGB hex values
-
-
Fox McCloud updated:
-
-
Fixes arm implants being immune to EMPs.
-
-
FreeStylaLT updated:
-
-
A dedicated toxic pill sprite, Cyanide and Toxin pills now use it by default.
-
-
KasparoVy updated:
-
-
Blood splattered by projectiles hitting a mob now land one tile away in the direction of the splatter graphic. Blood splattered on walls/windows/etc. can be cleaned off with soap.
-
Xeno-blood splatter is now the appropriate colour.
-
-
Kyep updated:
-
-
IAAs now require 10h of playtime, instead of 5h, to unlock. The IAA job's alt title is now "Human Resources Agent" instead of "Lawyer" or "Public Defender". IAAs now start with basic access to all departments (sci/med/cargo/eng), so that they can more easily conduct investigations. Overall, their role has been clarified, to be explicitly on the side of NT, not simply that of defendants. Further, they're empowered to, and expected to, actually conduct investigations, and generally be better at their jobs.
-
The mech bay next to Robotics now has a robotic storage unit (cryopod for cyborgs).
-
The Construction Site (partially finished space station east of eng outpost) has been revamped. With basic power/atmos networks in place, it should now be much more viable to repair it during a round.
-
Added shutters to specops office next to ERT spawn. This prevents borgs remotely activating the admin-only buttons in that office.
-
-
Tayyyyyyy updated:
-
-
Crew pinpointers no longer lose signal when the target enters something like a sleeper or a mech
-
-
Vivalas updated:
-
-
It is now possible to directly inject spaceacillin into organs during surgery, and it only uses 5u to completely cleanse the organ,
-
-
-
27 December 2017
-
Tayyyyyyy updated:
-
-
Repeated lines are now combined in the chat window. This can be disabled in chat window preferences.
-
Paramedic, Blueshield, and Medivends get crew pinpointers
-
-
-
23 December 2017
-
Fethas updated:
-
-
Borers can no longer be possesed by ghosts using an antag hud.
-
-
Fox McCloud updated:
-
-
Having a master, as a spider means you actually get a message who is your master now
-
-
Purpose2 updated:
-
-
Cartographers dispatched. NanoUI Minimap is now updated.
-
-
Santa's Lawyer updated:
-
-
Removed riot dart toys from under Christmas trees.
-
-
-
21 December 2017
-
FalseIncarnate updated:
-
-
Adds fans under the doors at the North Pole.
-
-
Purpose2 updated:
-
-
You may no longer use strikethroughs/italics in OOC. This was causing backend server problems due to how shoddily BYOND is coded, and cannot be safely added right now.
-
-
-
19 December 2017
-
Santa Claus updated:
-
-
Christmas cheer!
-
Grinch
-
missing emergency nitrogen / plasma tanks
-
-
-
15 December 2017
-
uraniummeltdown updated:
-
-
Plants no longer take twice as many cycles to age
-
-
-
05 December 2017
-
Kyep updated:
-
-
Removed peacekeeper borgs.
-
-
-
04 December 2017
-
Tayyyyyyy updated:
-
-
IPCs no longer vomit next to rotting bodies
-
-
Terillia updated:
-
-
Fixes the litch Hat and Sandals
-
-
-
02 December 2017
-
uraniummeltdown updated:
-
-
You can now create vault door assemblies with 4 plasteel sheets
-
Science airlocks have been added to metal recipes and the RCD
-
Airtight and Maintenance Hatch added to the RCD
-
Highsecurity airlock assemblies are built with 4 plasteel instead of 4 metal
-
All doors and doorlike things (firelock, airlock, windoor, blast door, shutters, spacepod door) run off the Environment Power Channel
-
Emagged airlocks have a different description on examining
-
Screwdrivering an airlock now displays a message. No more guessing if the panel is open or not.
-
Cult airlocks will keep their old name on being converted.
-
-
-
01 December 2017
-
Fox McCloud updated:
-
-
Lungs are now responsible for breathing instead of a mob; mix and match lungs however you like!
-
Ripping out someone's lungs or them necrotizing will make a person suffocate; it will no longer kill them instantly
-
Drask no longer heal burn damage from breathing cold air (brute is still healed)
-
Lungs no longer rupture in low pressure
-
Not having lungs means you can't talk
-
remove the discrete internals button on the HUD; use the tank action button!
-
Fixes slimes dying by themselves
-
-
-
30 November 2017
-
ExitGame updated:
-
-
vox quill rustle emote
-
species check
-
-
Fox McCloud updated:
-
-
shotgun pellets deal less damage the further they travel
-
-
-
28 November 2017
-
Kyep updated:
-
-
It is no longer possible for Service borgs using the Rapid Service Fabricator to end up with negative energy.
-
-
-
27 November 2017
-
uraniummeltdown updated:
-
-
Composting plants/pills into hydroponics trays transfers all reagents
-
-
-
26 November 2017
-
FalseIncarnate updated:
-
-
The Syndicate has determined that subtle and stealthy items don't benefit from obvious names, and thus have rebranded their contortionist jumpsuit to something less eye-catching.
-
The Syndicate decided to be less stingy than Nanotrasen and made the contortionist jumpsuit out of flame resistant materials. You may burn, but the jumpsuit won't!
-
-
Fethas updated:
-
-
Penguins, Penguins in shambreos and Albino penguins are a thing.
-
-
Fox McCloud updated:
-
-
Fixes being able to recall Abductor-called shuttles
-
Fixes slime transformation potion not making you a real slime
-
Polymorph slimes are now random color
-
-
Jountax updated:
-
-
Can now add laceup shoes to your loadout.
-
-
Kyep updated:
-
-
Service borgs are now able to dispense a variety of fruit juices, as well as coffee and tea. Additionally, they can use a health scanner on crew, and the poisoned beer they get from being emagged is much more deadly. They can also create snackfood using their Rapid Service Fabricator.
-
When an admin creates a classified message manually, and selects 'no' to the 'notify crew' option, the incoming message will be announced via command radio, instead of a priority announcement that the whole crew sees.
-
ERT borgs can now speak on ERT radio, even after choosing a module.
-
ERT borgs are now always named as such, may only take modules that would be useful in an emergency, and always have their emagged modules unlocked. They also have an 80% chance to resist emagging their cover lock, so you will need to stun them with a flash before trying to emag them.
-
-
MarsM0nd updated:
-
-
Logs usage of stun talismans.
-
Stops rigsuits from shocking over distance.
-
Let's malfunction count down while not being actively worn, to avoid permanetly breaking it.
-
Allows boots to be worn under rigsuit boots.
-
Wirenames for the rigsuit wires if you can see them.
-
Rigsuits only slow you down when deployed, potentially less if active.
-
-
Ty-Omaha updated:
-
-
Gambling machines now payout again.
-
-
uraniummeltdown updated:
-
-
Particle effects pass over tables and grilles
-
Nanofrost smoke fading out actually works now
-
All smokes now fade out
-
Nanofrost smoke can now also weld scrubbers
-
-
-
22 November 2017
-
Fox McCloud updated:
-
-
"Pick Up" from right clicking obeying the same rules as regularly clicking on it
-
-
-
19 November 2017
-
Fox McCloud updated:
-
-
Fixes cult shuttle curse from being used more than twice and from extending shuttle call duration once nar-sie has been called/slaughter demons have been called.
-
-
-
18 November 2017
-
MarsM0nd updated:
-
-
A (possibly non-existant) officer's beret does no longer incorrectly hide hair.
-
-
-
13 November 2017
-
Alffd updated:
-
-
Fixes muzzles not preventing vampire biting unless the target was wearing the muzzle.
-
Makes throwing the ambulance with atmospherics almost impossible.
-
-
VexingRaven updated:
-
-
Fixes the message that appears when a mob being force-fed a snack finishes eating that snack.
-
-
-
12 November 2017
-
Kyep updated:
-
-
It is now much harder for Command/HoS to get away with illegal executions. Admins are far more likely to notice people being set to execute, more detailed explanations of executions must be sent to CC, and admins are more able to intervene when an execution is obviously illegal.
-
-
-
11 November 2017
-
FalseIncarnate updated:
-
-
Full windows are now 100% stronger than before, so you don't have to pick strength over security.
-
Full windows now take longer to deconstruct so they offer slightly better security against break-ins. Toolspeed does apply.
-
Full and directional windows can be built on grilles now, and you can even pick the direction! Technically both a tweak and an addition...
-
-
-
10 November 2017
-
Allfd updated:
-
-
A new Anti-Bite muzzle has been added to the SecVendor. This muzzle can be locked through the strip panel and will prevent a vampire from feeding.
-
Holy water now causes vampires to vomit blood, before vomiting the water. After this holywater behaves as normal.
-
-
Anasari updated:
-
-
79 hairstyles ported from Polaris.
-
-
-
05 November 2017
-
Fethas updated:
-
-
changes the my tickets from a verb..to a prock. To quote lemons: F.
-
-
KasparoVy updated:
-
-
The Barber's dye bottle now works again.
-
The Barber's dye bottle can now colour alternate (facial) hair themes where applicable.
-
-
-
04 November 2017
-
FalseIncarnate updated:
-
-
MANDATORY FUN! Arcades added to both stations!
-
Bottler units have been spotted on board both stations!
-
Arcade carpet tiles added to the prize counter for 150 tickets (credit to Goonstation for the turf icon).
-
Cyberiad bathrooms should have 100% fewer floating showers (behind curtains).
-
Showers have been fitted with mist-reducing showerheads. They should no longer generate infinite mist if rapidly toggled.
-
Cyberiad chemistry has had the extra APC removed. Now they only have one as standard.
-
-
FreeStylaLT updated:
-
-
Medbay has been remapped
-
New Maint areas have been added south of Medbay.
-
-
-
01 November 2017
-
FreeStylaLT updated:
-
-
Medbay has been remapped
-
New Maint areas have been added south of Medbay.
-
-
Kyep updated:
-
-
Freedom Operative suits no longer revert to a normal red syndi suit icon when you use their 'toggle hardsuit mode' option.
-
-
MarsM0nd updated:
-
-
Stops holograms from attempting to appear when they just disappeared because the AI became unable to keep it up.
-
-
-
30 October 2017
-
NewSta updated:
-
-
There is now a "GitHub" button.
-
Modified the height of the "Donate" button to make it equal to that of other buttons.
-
The distance between the info and wiki buttons is now 30 px. All other buttons now have a 5px distance between them.
-
Fixed a typo in the wiki window.
-
-
-
29 October 2017
-
Alffd updated:
-
-
Ion Rifles are no longer pistols
-
-
-
28 October 2017
-
Anasari updated:
-
-
Some underappreciated traitor items had been made cheaper.
-
-
Kyep updated:
-
-
Vamp jaunt/shadowstep no longer works on z2.
-
Ghosts with sec hud enabled can now see mindshield, tracker and chem implants, as well as wanted status.
-
-
Landerlow updated:
-
-
Adds Sake to a hacked booze dispenser's menu.
-
-
Squirgenheimer updated:
-
-
Fixed a typo causing the inability to create the large energy crossbow in the protolathe.
-
-
-
27 October 2017
-
Birdtalon updated:
-
-
Birdtickets: Adminhelp Ticketing System
-
-
FalseIncarnate updated:
-
-
Silver Slime Core reactions can only summon forth drinks that actually contain a drink. Begone thirst!
-
Removes some "unsafe" chemicals from lists of potential chemicals for inclusion in things like random pills or bottles, added one to replace them.
-
Removes adminordrazine and nanites from vent clog, replaces nanites with syndicate_nanites.
-
-
-
26 October 2017
-
Anasari updated:
-
-
Change some brain damage phrases. Add a lot of new one.
-
-
FreeStylaLT updated:
-
-
Moves Ambulance's key to Paramedic's EVA locker from his clothing locker
-
Removed an unnecessary EVA helmet from Paramedic's EVA locker
-
-
Kyep updated:
-
-
Soviets (including Soviet Tourists, a non-antag filler role) no longer get all-access to the Cyberiad when they visit.
-
Freedom Operatives are now a support outfit that admins can equip players as.
-
-
TDSSS updated:
-
-
Added a shortcut to talk on ERT channel, namely ':$', bringing it in line with other channels.
-
-
-
25 October 2017
-
Anasari updated:
-
-
Flavour text description in character setup now consistent with rules.
-
Grenade reagent are also logged when they are primed
-
TC from war op increased by 2 per player above 50.
-
-
Kyep updated:
-
-
ERTs now support janitor, paranormal, and cyborg ERT units, as well as specific slot configurations.
-
Heads of staff who are editing another admin's permissions in the admin panel can now toggle several permissions for a person without re-finding them in the list. Hitting 'cancel' at any point drops out of the loop. It also notifies admins whether they're toggling a permission on, or off.
-
ERT spawn area now shows ERT request reasons, and admins can enable the use of a teleporter or grav catapult without mechs.
-
-
-
22 October 2017
-
Crazylemon64 updated:
-
-
Suiciding crewmembers are no longer capable of being cloned.
-
-
Fethas updated:
-
-
makes a better proc for doing spins (IE Ian chasing tail, etc) then was previous.
-
-
McCloud and Alffd updated:
-
-
Merge all LINDA and atmos machine functions into the air controller subprocess.
-
Air alarms in scrubbing mode will shut off when alarm enters danger state. If this occurs simultaneously with a max2 temperature alarm panic siphon will automatically activate.
-
High air pressure differences will throw objects and knock over station species.
-
Add magpulse to syndicate and death squad borgs.
-
Change all volume pumps to regular pumps in atmospherics to accommodate new LINDA speeds.
-
Change LINDA interval from 2 seconds to 400 milliseconds.
-
Removed unused control from flamethrower.
-
Set flamethrower release equal to fuel used.
-
Increased Reinforced Wall HP from 200 to 600.
-
Buff aliens against space wind.
-
Buff Terror Spiders against space wind.
-
Buff some blobmobs aginst space wind.
-
Frost requires heat to remove.
-
-
-
15 October 2017
-
Citinited updated:
-
-
Clipboards now have more functionality. You can now stamp them, attach paper bundles to them, write on any contained paper by clicking on the paper's name using a pen, add pens directly to them, and rearrange what piece of paper is on top!
-
Full-sized plasma windows are fire-resistant, and full-sized reinforced windows are fully fireproof.
-
You can now remove facehuggers from corgis. Corgis that have been glomped by multiple facehuggers will now work as you'd expect them to.
-
Radiation mines no longer change the DNA of species that don't have it.
-
Firedoors and other doors will no longer close when a shuttle docks. Open firelocks can no longer be welded. Welded firelocks should no longer open under any circumstances.
-
Open airlocks no longer spark when you throw something conductive through them.
-
-
Fethas updated:
-
-
Many things use sleeping. Surgry pain fail fix.
-
-
Imsxz updated:
-
-
Ballistic mech weapons now all use the ammo system
-
-
Kyep updated:
-
-
Changing someone's sec status now prompts for a reason. The change, and the (optional) reason for it, is written to that person's sec record, and to the server logs. This applies to changes made by sec HUDs, and by records computers.
-
Magistrate/Captain/HoS/Warden can now use a sec records computer to set a person to "Execute" status. This status cannot be unset by HUDs, and broadcasts a notification to all online admins when it is set. It is intended to replace the "fax CC" requirement for executions. Persons with this status show up with a white 'X' as their sec hud icon.
-
-
TullyBurnalot updated:
-
-
Shadowlings are extinguished after hatching, allowing Plasmamen Shadowlings to not burn to death.
-
Shadowlings now passively heal eye damage, eye blurriness
-
-
Vivalas updated:
-
-
Splints now pop off after 2000 steps, or when taking a lot of damage to that limb. Getting surgery for those broken limbs might be a good idea now.
-
-
-
14 October 2017
-
Anasari updated:
-
-
Explosive lance doesn't embed anymore.
-
-
Fethas updated:
-
-
ARMBANDS! REPRESENT! SEE THE LOADOUT!
-
-
Kyep updated:
-
-
HoPs/Captains opening/closing job slots is now announced to admins. No more HoPs opening 30 clown slots without admins noticing.
-
-
MarsM0nd updated:
-
-
Gives a choice whether to mangle black gloves, or to completely cut of the fingertips
-
-
-
11 October 2017
-
Anasari updated:
-
-
Slot machine no longer earn money on average. Bet changed to 100.
-
All items can be used to smash windows instead of only those defined as weapons. (e.g. including guitar & flashlight)
-
Mulebot with pAI cannot knock people down anymore.
-
-
Birdtalon updated:
-
-
Terror spiders now respect antagHUD respawn restrictions.
-
-
Kyep updated:
-
-
mindslaving an antagbanned player now offers control of their mob to ghosts.
-
-
TullyBurnalot updated:
-
-
Can now place garbage in garbage cans without standing on top of them.
-
-
scrubmcnoob updated:
-
-
Cult must use teleport tailsman in active hands.
-
-
uraniummeltdown updated:
-
-
New PACMAN portable generator sprites
-
-
-
10 October 2017
-
Birdtalon updated:
-
-
Bees with no reagent will now work.
-
-
-
07 October 2017
-
Birdtalon updated:
-
-
User interface tweaks to Brig timers.
-
Seconds converted to minutes and seconds in Brig radio and security console printouts.
-
Bees can no longer reproduce un-synthable reagents.
-
-
imsxz updated:
-
-
Aliens now always spawn as a pair when their infestation event begins.
-
-
scrubmcnoob updated:
-
-
Abductors can no longer use megaphones.
-
-
uraniummeltdown updated:
-
-
Adds new sprites to the unused and used eldritch whetstones. Sprites by Fury McFlurry.
-
Air tanks now have their own sprite, no longer looking like oxygen tanks
-
10mm alt magazines have their own sprites
-
-
-
06 October 2017
-
Birdtalon updated:
-
-
Bottler doesn't break after one use.
-
-
-
05 October 2017
-
Birdtalon updated:
-
-
Re-adds missing light switch to robotics.
-
-
-
02 October 2017
-
Imsxz updated:
-
-
Rapid re-hatch no longer kills shadowlings.
-
Vampires can no longer enthrall chaplains
-
-
-
30 September 2017
-
Jovaniph updated:
-
-
Coroner now has their own locker in the morgue.
-
-
Landerlow updated:
-
-
Adds hydrocodone to the Cyborg Hypospray
-
-
-
29 September 2017
-
Citinited updated:
-
-
Telescreens and entertainment consoles now have 'off' and 'broken' sprites.
-
Wooden TVs, engineering camera consoles, mining camera consoles, telescreens, and entertainment consoles now have their own circuit boards and can be reconstructed!
-
Using a multitool on a telescreen or entertainment monitor will now allow you to reposition it.
-
-
imsxz updated:
-
-
Subtle messages no longer begin with "old"
-
-
-
28 September 2017
-
MarsM0nd updated:
-
-
Stops the electrified arm from combat and stunbaton implant from runtiming.
-
-
uraniummeltdown updated:
-
-
Changelings have a new power, Biodegrade, for 2 evolution points. For 30 chemicals you can vomit acid onto restraints, welded/locked lockers and spider cocoons to escape them.
-
Hivemind Link for changelings has been readded, it was removed in error
-
-
-
05 September 2017
-
Kyep updated:
-
-
Adds alternative military shuttle, NT Navy troop transport.
-
-
-
04 September 2017
-
Kyep updated:
-
-
Admins under the effects of 'invisimin' no longer show up on sec huds, medical huds, etc.
-
-
-
03 September 2017
-
Birdtalon updated:
-
-
Flip emote has a small chance of a failure and 100% chance of embarrassing yourself.
-
-
Citinited updated:
-
-
You can now deconstruct the indestructible stool in the old bar's back room.
-
Security and bar maintenance airlocks are now decoupled.
-
The air vent at the fore of AI satellite now starts turned on.
-
Engineering equipment now only has one air vent, not three.
-
Added a missing bit of plating underneath the engineering shuttle's window.
-
Added a missing scrubbers pipe in Central Primary.
-
The camera and light fixture in the prisoner transfer centre are now wall-mounted instead of being attached to the blast doors.
-
Adds the Flaming Moe cocktail.
-
Shot glasses can now be set alight using something hot.
-
-
-
02 September 2017
-
Landerlow updated:
-
-
Adds a recipe to create enzymes to cook with.
-
-
-
01 September 2017
-
Birdtalon updated:
-
-
Fixed small bug with wall lockers not respecting distance.
-
-
-
28 August 2017
-
Birdtalon updated:
-
-
Replaces civilian door remote in the Head of Personnel locker with a brand new remote with additional access to better suit the Head of Personnel's responsibilities.
-
Nanotrasen Mining Bots are no longer safe from EMPs.
-
Syndicate bee-case sound now only plays locally when opened.
-
You can open wall lockers with control click.
-
-
Birdtalon & Hylocereus updated:
-
-
Adds pineapples which can be grown in hydroponics, juiced or sliced and made into hawaiian pizza.
-
Adds hawaiian pizza to the pizza crate.
-
-
Fethas updated:
-
-
The cultist dagger has had its special removed, it still cuases small bleed and retains its embed chance.
-
Prayers now dsiplay the diety set by chaplains (if any) to admins in prayers, or eldergod if a cultist. Prayers are purple for normies, Red for cultist and blue for chaplains
-
-
Fox McCloud updated:
-
-
IPCs can now be dissected by adbudctors
-
-
Fox Mccloud updated:
-
-
Adds an accordian, glockenspiel, harmonica, recorder, saxaphone, trombone, xylophone, bikehorn, and piano synthesizer
-
pick up a big band supply pack of instruments at cargo for 50 supply points
-
-
Jovaniph updated:
-
-
Holodeck Energy Swords sound was change to simulate being attacked by a real energy sword.
-
-
Landerlow updated:
-
-
Adds six additional roundstart disabilities to choose from
-
-
matt81093 updated:
-
-
robot analyzer to medical module cyborgs for IPC diagnosing
-
-
-
24 August 2017
-
Birdtalon updated:
-
-
Cultist structures can now be destroyed using melee and or projectiles
-
-
Fox McCloud updated:
-
-
Fixes Diona, Plasmamen, and other races having internal bleeding
-
-
-
16 August 2017
-
Citinited updated:
-
-
Adds the plasmaman flag; credit to Shadeykins for the original sprite! Buy it at the merch store and show your superiority over other, less flammable, species!
-
All flags should now have in-hand sprites.
-
Burning a flag while it is in your hand will now update your mob's sprite.
-
Fixes another issue with disposals sending things to nullspace.
-
-
Fethas updated:
-
-
Swarmers can now deconstruct simply by clicking, ctrl click to teleport.
-
you can now deactivate depowered swarmers with a screwdriver.
-
Swarmers can now consume swarmer shells for a refund.
-
swarmer lights are cyan.
-
-
Fox McCloud updated:
-
-
Cluwning is far more difficult to remove
-
Cluwne mask cannot be melted with acid
-
Cluwne suit has no sensors
-
-
Kyep updated:
-
-
Admins now have a 'List SSDs' verb to list SSD players, and the ability to move them to cryo.
-
-
-
15 August 2017
-
Birdtalon updated:
-
-
Medbots can now inject from their internal beakers.
-
Swarmers can no longer kill the AI with direct attacks.
-
Simple animal melee damage now has a sanity check for AI core.
-
-
-
14 August 2017
-
AndrewMontagne updated:
-
-
Modular computers now print fields correctly.
-
Files on modular computers no longer vanish shortly after editing.
-
Modular computers printers now make printing noises.
-
You can no longer try and buy a tablet with a printer.
-
Cloning a file now works.
-
-
Birdtalon updated:
-
-
Spiderbots can now pass tables, making their Hide worthwhile.
-
Fixes interactions with cargo crates.
-
-
Citinited updated:
-
-
Nanotrasen's legal department clamped down on video cameras being misappropriated by crew, and as such cameras are now unable to broadcast from beyond the gateway.
-
-
Fethas updated:
-
-
Dethaws some IPC surgery issues.
-
-
taukausanake updated:
-
-
Adds an Atmospherics duffel bag that is yellow and blue
-
Adds sub-department colors to medical duffel bags and purple to Science duffel bags
-
Captain's lefthand west sprite corrected
-
-
-
10 August 2017
-
KasparoVy updated:
-
-
Blood trails are now the same colour as the blood pools they came from when viewed by colour blind or noir shades wearing humanoids.
-
-
-
09 August 2017
-
Purpose2 updated:
-
-
Adds a cycling airlock on the new mining mini outpost.
-
Re-adds the cycling airlock on mining outpost.
-
Fixes the broken atmos piping on mining outpost.
-
Fixes a lack of lighting on mining outpost.
-
-
-
06 August 2017
-
Birdtalon updated:
-
-
Small wording change to syndicate collaborator greetings.
-
-
Fox McCloud updated:
-
-
Botany nerfed; will need ambrosia gaia earth's blood to make a tray self-sustaining
-
Gene machine now requires heavy upgrading to make use of transferring high quality genes from one plant to another
-
Starthistle can now be grown
-
Adds in red and regular onions; slice them for onion rings; cook them for even more delicious onion rings
-
-
Kyep updated:
-
-
Playing as a smite/bless hunter, or syndie infiltration team member, now requires that you be traitor-eligible. IE: have enough playtime, and the preference enabled.
-
-
Purpose2 updated:
-
-
BoxStation: Adds a garbage receptacle by the kitchen. Don't forget to bus your plates.
-
BoxStation: Fixes an inappropriate access restriction on one part of an airlock, and ensures the buttons are visible.
-
BoxStation: Changes the now erroneous Science Shuttle Console on the bridge to a Labor Camp Shuttle Console.
-
Adds screwdrivers to Medical by the cell chargers for recharging the defibs.
-
-
-
05 August 2017
-
Purpose2 updated:
-
-
Karma message will now point you in the right direction again.
-
-
-
03 August 2017
-
Fox McCloud updated:
-
-
Internal organs can take damage again, brain damage can be fixed again, and you now take the proper damage from external sources to limbs, IPCs surviving EMPs, and robo limbs never malfunctioning
-
-
-
02 August 2017
-
Fox McCloud updated:
-
-
removed a stasis book from the medical break room
-
-
-
31 July 2017
-
Birdtalon updated:
-
-
Protolathe stock part printing no longer takes a lifetime.
-
-
-
30 July 2017
-
FreeStylaLT updated:
-
-
Fixed erroneous pipes on z5
-
-
Kyep updated:
-
-
Evil-minded players can no longer use the Gateway's Mother of Terror spider to create an infestation on-station.
-
-
-
29 July 2017
-
Fox McCloud updated:
-
-
Dead hearts now induce a heart attack
-
Fixed concentrated initro never metabolizing
-
-
FreeStylaLT updated:
-
-
replaces generic Mining z-level with Meta's
-
-
Purpose2 updated:
-
-
MetaStation: Adds the missing kitchen windows
-
MetaStation: Nerfs the Top Hat equivalent of the Sword in the Stone.
-
MetaStation: Adds a Pet Supply vendor, chefs now make sushi again!
-
-
-
27 July 2017
-
Birdtalon updated:
-
-
Protolathe speed now increases when upgraded with manipulators.
-
-
-
26 July 2017
-
Citinited updated:
-
-
The autopsy drawer's description makes more sense.
-
-
-
25 July 2017
-
Birdtalon updated:
-
-
Reduces the volume of the electric guitars
-
-
FlattestGuitar updated:
-
-
Antagonists will no longer get the objective to steal slime extracts and plasma tanks.
-
The Captain has a swanky high-tech jetpack now. Antagonists will try to steal this one instead of *any* jetpack.
-
-
Fox McCloud updated:
-
-
You can now point while voluntarily lying down
-
shotgun darts and syringe darts no longer react their reagents on hit (they will still transfer reagents)
-
removes cryostasis bag
-
-
FreeStylaLT updated:
-
-
Removed sci outpost and dock from Metastation and Cyberiad
-
Added a Mining Outpost to the northernmost point of the Asteroid.
-
-
Kluys, Kyep & DarkLordpyro updated:
-
-
Emagged drones are now readily identifiable, as their lights turn red.
-
-
Kyep updated:
-
-
Eating as Ian (and other player-controlled corgis) is now rate-limited.
-
Reagents placed in shotgun shells will now react. It is no longer possible to make explosive shotgun darts by using regular darts like cryobeakers.
-
Admins' Smite command has been upgraded. No longer limited to Dark Priests, it can now send over a dozen different entities in search of its target, from the comic, like Greytiders, Tunnel Clowns, Masked Killers and Mime Assasins, to the serious, such as Syndicates, Soviets, Dark Lords and more. All come with a dust implant. These same characters can also be sent to protect specific crew members, so they aren't predictable.
-
The 'reaper' admin outfit now has a working briefcase.
-
Use of the 'Bless' command to bestow powers no longer causes genetic damage.
-
-
imsxz updated:
-
-
makes HONK rifle selfcharge
-
-
owenowen212 updated:
-
-
Adds the clownish language to honk squad members.
-
-
-
24 July 2017
-
FlattestGuitar updated:
-
-
Adds a taste system! Drink or eat stuff to find out what it tastes like!
-
-
Kyep updated:
-
-
it is no longer possible to use a sentience potion to convert space pirates in the beach away mission to your side. Nor is this possible with other sentient NPCs, such as syndies or russians.
-
-
-
23 July 2017
-
Fox McCloud updated:
-
-
Fixes cloners causing infections in clonees
-
-
-
22 July 2017
-
Crazylemon64 updated:
-
-
Slipping now outputs a visible message instead of a personal one
-
-
Fox McCloud updated:
-
-
Fixes IPCs and Diona being immune to weapon knockdown
-
-
Kyep updated:
-
-
Terror Spider away mission is now harder to cheese.
-
Loading a different character while in the lobby will now update the character name listed on the lobby screen. Same when you rename an existing character.
-
Blood decals are no longer movable. This means LINDA cannot move them, spiders cannot wrap them, etc.
-
-
-
21 July 2017
-
Purpose2 updated:
-
-
MetaStation: Adds a brand new Medbay!
-
MetaStation: Adds the dogbeds to the CMO/HoS office
-
MetaStation: Adds Sergeant Araneus back to the HoS's office. HoS beware.
-
MetaStation: Adds a processing area to the brig.
-
MetaStation: Adds the Gamma Armory.
-
MetaStation: Adds two additional brig cells
-
MetaStation: Adds a morgue slab to the Brig Phys office
-
MetaStation: Morgue has a swanky new office, directly connected to Cloning.
-
MetaStation: Robotics gets gloves and masks.
-
MetaStation: Adds shutters to R&D and Genetics.
-
MetaStation: Adds a Paramedic's office.
-
MetaStation: Adds a fully function containment grid.
-
MetaStation: Moves Monitor Encryption key to the RD's office again
-
MetaStation: Dorms have glass doors and fewer tinted windows
-
Metastation: Engine Containment now has Blast Doors instead of Shutters.
-
Metastation: Execution chamber blast doors are no longer see-through.
-
Metastation: Only the appropriate plastic flaps should be see-through.
-
MetaStation: Botany is no longer all-access
-
MetaStation: Science gets access to the Science outpost again... for now...
-
MetaStation: Fixes camera network monitors
-
MetaStation: Church shutters block vision again
-
MetaStation: Adds the missing Armory shutter button.
-
MetaStation: Removes tinted windows from R&D & Genetics
-
-
-
20 July 2017
-
Purpose2 updated:
-
-
Stops vampires spawning in the church.
-
-
-
19 July 2017
-
Fox McCloud updated:
-
-
Fixes dismembering and some damage transfers (when limb damage is maxed out) being inconsistent
-
can no longer dismember groins
-
Cleans up human examine code to be better laid out and more consistent; minor grammatical changes and some fixes; consistency should be retained for species that lack a pulse. Soul departure now properly checks for if the person can re-enter their corpse or not. Also resolves issues with FAKE DEATH examination.
-
Adds in gunshot blood splattering
-
-
-
18 July 2017
-
Fox McCloud updated:
-
-
Fixes blood volume being able to exceed 560
-
-
Purpose2 updated:
-
-
The Arrival's Trader Dock now cycles properly.
-
-
-
16 July 2017
-
Ataman updated:
-
-
Fixed diona nymphs needing oxygen and getting cold.
-
-
Crazylemon64 updated:
-
-
Cable laying by clicking the cable you want to join to works now
-
-
KasparoVy updated:
-
-
Fixes a bug with Vampire Shapeshift where you didn't get a name appropriate to your species and clarifies the ability description.
-
Fixes a bug with DNA scramblers whereby you wouldn't get a name appropriate to your species.
-
-
-
15 July 2017
-
Fox McCloud updated:
-
-
Fixes blood oddities with vampires
-
-
Kyep updated:
-
-
Mechs firing missiles no longer cause the missiles to drop at their feet, as if frozen in midair.
-
-
imsxz updated:
-
-
Edits the syndicate soft suit helmet's description to match the suit's.
-
-
-
13 July 2017
-
Fox McCloud updated:
-
-
Fixes blood volume and type not showing up properly on health analyzer
-
Fixes exotic blood names being incorrect
-
fix examining/checking yourself/others for bleeding/bandaging
-
Everything that involves bandaging now properly uses the new blood system
-
Fixes species exotic blood being injected into a mob not increasing their blood volume (slimes rejoice)
-
Fixed faked deaths still allowing for bleeding
-
Fixes IV drips not transferring over the proper amount of blood
-
Embedded objects will cause additional bleeding
-
Adds in heparin, a drug that can cause bleeding
-
medical stacks can be used multiple times on the same limb
-
Blood depletes in the body a lot faster now, due to blood refactor changes
some diseases now bypasse species virus immunity (kuru, TB, and appendicitis)
-
-
-
11 July 2017
-
Fethas and tigercat updated:
-
-
blood trails
-
blood is now eaiser to decrease/increase .
-
revamps about every method of adding blood to something, floors, walls, doors, PEOPLE.
-
-
-
10 July 2017
-
AffectedArc07 updated:
-
-
APC frames now have the correct texture
-
-
Birdtalon updated:
-
-
Pool contractors have been back to school and can now spell "safety" on the controller correctly.
-
Minor change to blob description to address grammar issue.
-
-
Citinited updated:
-
-
Superfart once again works ass intended.
-
-
Fox McCloud updated:
-
-
Radiation poisoning no longer permastuns, but deals burn damage now and has increased mutation chances
-
adds in electric guitars
-
can now craft violins and electric guitars
-
purchase electric guitars at the cargo store
-
service borgs now have an electric guitar, too
-
lowered the price of instruments, at cargo store, to 500
-
Fixed violins not having an in-hand icon
-
-
-
08 July 2017
-
Citinited updated:
-
-
Rainbow and mime crayons will now change colour as intended.
-
-
Fox McCloud updated:
-
-
Advanced mop slightly slower at cleaning and holds less reagents, but now regenerates water if turned on
-
Blood (on the floor) that has viruses in it will now properly infect you, if you get near
-
-
Kyep updated:
-
-
It is no longer possible to prioritize a job with no open slots, or close any job slots for a job that is already prioritized, as either of these actions could lead to a situation where a job is prioritized without people being able to join as it.
-
-
-
05 July 2017
-
Purpose2 updated:
-
-
Anomalies will once again drop cores.
-
-
-
04 July 2017
-
Birdtalon updated:
-
-
Traitor medical chemists can now access syndicate poison bottles.
-
-
Citinited updated:
-
-
AIs and cyborgs can now toggle liquid dispensers by ctrl-clicking them, and can make them dispense foam by alt-clicking.
-
-
Citinited & LightFire53 updated:
-
-
Adds the plasmaman coroner suit, the plasmaman geneticist suit, and the plasmaman virologist suit. Spooky purple skeletons everywhere rejoice!
-
-
Fethas updated:
-
-
Adds medical gowns to medical wardrobes.
-
-
Fox McCloud updated:
-
-
Syndicate bombs now have visible timers for observers
-
Syndicate bombs tick more often
-
Syndnicate bombs can be deconstructed into plasteel if it is fully defused and has no bomb core
-
Can make Cryo, Pyro, and time released chemical grenades at R&D
-
Can make syndicate chemical bombs utilizing crafting
-
love just got more powerful; it now prevents a mob from being on anything other than help intent
-
IPCs can now process the love reagent
-
Adds in radio jammers to the traitor uplink
-
Adds in breathing tube augment to R&D
-
Adds in arm toolset augment to R&D
-
IPC cell charging device is now inside their right arm, as opposed to chest
-
IPC cell charging device can now be produced in mech fabricators
-
-
Ionward updated:
-
-
Greys now have properly fitting sprites for most head clothing items!
-
-
Kyep updated:
-
-
Gimmick Teams are now more configurable.
-
-
Vivalas updated:
-
-
"Tweaks" SecHUDs to only display criminal status of people if their face is uncovered or they have no ID.
-
-
-
03 July 2017
-
Fethas updated:
-
-
fixes issue with hand teleporter not working in active hands
-
-
fludd12 updated:
-
-
Greys are now PROPERLY immune to sulfuric acid.
-
Greys don't pretend to touch their heads when they don't manage to anymore.
-
-
-
01 July 2017
-
Fox McCloud updated:
-
-
Re-enables object embedding system; embedding objects now cause more damage than before
-
Adds in throwing stars kit to the traitor uplink
-
bullets no longer leave shrapnel
-
-
-
30 June 2017
-
fludd12 updated:
-
-
Greys treat Sulfuric Acid as if it were water. They also treat water as if it were sulfuric acid.
-
Grey language is now Z-level wide, but requires you to be able to put a finger to your temple. (Requires at least one hand not disabled and not stunned.)
-
Remote Talk is buffed to have a range of two screens, and has some minor formatting changes!
-
Remote Talk no longer lets you magically know the true name of whoever you speak with.
-
-
-
29 June 2017
-
Fox McCloud updated:
-
-
Fixes limbs being an open wound after augmentation
-
-
Kluys updated:
-
-
Bob ross painting in the captains office called "calming painting".
-Also changes around the entertainment monitor and light switch to accomodate.
-
Clown painting was named "\improper mech painting"
-
-
-
28 June 2017
-
Fox McCloud updated:
-
-
Fix's IPC head customization
-
-
Purpose2 and Re-Opened by Fethas updated:
-
-
Rare Sentience event, the mice now want coffee!
-
-
-
27 June 2017
-
Alexshreds updated:
-
-
EMPs now disable radios for a period of time
-
-
Citinited updated:
-
-
Adds the Rapid Pipe Dispenser (RPD). All Atmospherics Technician lockers and the Chief Engineer's locker get one each.
-
-
Code Fethas and Sprites Phantasmicdream updated:
-
-
Fancy Victorian Clothes
-
-
FlattestGuitar updated:
-
-
defibs work even if you don't target the chest
-
Chaplain's soul stone is now opt-in.
-
-
Fox McCloud updated:
-
-
Can now augment all non-head limbs with surgery
-
Can select the company design of a limb by using a robot part in your hands
-
-
Kyep updated:
-
-
Gamma ship now looks like a real supply pod/ship, doesn't encourage wizards/vampires to hide in it, and has been updated with a wall-mounted charger and smarter layout.
-
Fixed a bug causing gamma armory mech recharger to be unusable after gamma alert was declared.
-
Admins may now spawn 'Gimmick' teams, including Janitorial ERT, Paranormal ERT, and more. Any admin outfit, any mission, spawned anywhere.
-
Paranormal ERT outfit now exists. It acts like a red security ERT, except with focus on fighting paranormal threats.
-
Janitorial ERT now gets ERT headset, not centcom headset. Also, they now get a survival box, and a flashlight.
-
New 'department' shuttle now has more public-access seating.
-
-
ProperPants updated:
-
-
Plasmaman virologists now spawn with a medical plasmasuit instead of an assistant one.
-
-
Purpose2 updated:
-
-
Water coolers have been fitted with better bolts, enabling them to be loosened and moved.
-
Antag barbers scissors now have the same name as regular scissors.
-
AIs door open link is now [O] rather than [OPEN].
-
The Syndicate once more recognises the Coroner as a member of the medical team for purposes for uplink items.
-
The chef may now tap into the Syndicate's poison networks for use in his dishes.
-
The chef's supply crate now comes with another rolling pin. Stop misplacing these.
-
-
tigercat2000 updated:
-
-
Karma returned to the Special Verbs tab
-
-
-
26 June 2017
-
Crazylemon64 updated:
-
-
TK can now manipulate adjacent tiles. Use throw mode to override this if you want to move an object a single tile.
-
TK can now remotely manipulate item stacks.
-
TK can now remotely operate an RCD
-
TK now behaves more consistently regarding interacting with various objects remotely
-
-
Kyep updated:
-
-
ID card consoles can now be used to prioritize any on-station job, including head jobs and karma jobs.
-
Playing as a drone now requires 10h of playtime.
-
Admin-ghosts can now interact with (ie: activate) the drone fab without having to spawn in as engineer to do so.
-
Prioritized jobs now lose their priority status once all their slots are filled. In the event someone with a formerly prioritized job cryos, the HoP may want to re-prioritize the job.
-
-
Purpose2 updated:
-
-
Coroners are more battlehardened, and thus don't throw up around dead bodies anymore.
-
-
-
25 June 2017
-
Kyep updated:
-
-
Trial admins no longer see a permissions error when opening player panel.
-
-
-
24 June 2017
-
Allfd updated:
-
-
Ported growl and howl sounds from Goon
-
Added growl and howl emotes to Vulpkanin
-
-
Kyep updated:
-
-
Activating a dust implant no longer causes NODROP items to drop.
-
-
Purpose2 updated:
-
-
The *slap emote now has a cooldown like all other noise making emotes.
-
-
SamHPurp updated:
-
-
The Coroner will respect the CMO's Authoritah.
-
-
-
23 June 2017
-
Kyep updated:
-
-
Smite/Bless commands are now restricted to Game Admins. (admins with R_EVENT)
-
Admins can now access telecomms while ghosted.
-
-
Vivalas updated:
-
-
Buckling mobs to beds now displays them correctly.
-
-
-
22 June 2017
-
Crazylemon64 updated:
-
-
Cloners now malfunction if the original comes back to life
-
-
Purpose2 updated:
-
-
RCDs can no longer construct multiple airlocks on a single tile
-
-
-
21 June 2017
-
tigercat2000 updated:
-
-
Changelings are now tentacle monsters. Give them a schoolgirl outfit.
-
-
-
20 June 2017
-
Purpose2 updated:
-
-
Fixes Fluorine's non-functionality in plants.
-
-
-
19 June 2017
-
Fox McCloud updated:
-
-
Diona nutrition bar should no longer flicker constantly
-
-
-
18 June 2017
-
Citinited updated:
-
-
Using a screwdriver on a camera console will now deconstruct it instead of opening the camera window.
-
-
-
16 June 2017
-
Alffd updated:
-
-
Makes kittens visible when resting
-
-
Fethas updated:
-
-
Public Wiggler Tail
-
Chaplains have some new clothes in thier locker.
-
-
Fox McCloud updated:
-
-
tweaked Revenant and slaughter demon movement speed
-
Spiderbots have been slowed down to human levels
-
Spiderbots melee attack consistently deals 2 damage, deals burn, and plays a sparks sound
-
Spiderbots no longer have a built in camera
-
Spiderbots now have 40 health (previously 10)
-
Attacking a spiderbot more consistent with other simple mobs
-
Healing a spiderbot with a welder now plays a sound and incurs a cooldown
-
Spiderbots can no longer carry items
-
Emagging a spiderbot makes it loyal to the person who emagged it. Additionally, it gains 20 extra health, its shocks will do 15 damage, and will explode on death
-
-
FreeStylaLT updated:
-
-
Changed Araneus' spawn location so he wouldn't break tables at round-start anymore
-
-
Kyep updated:
-
-
HoPs can now set jobs as 'priority'. Priority jobs are highlighted on the latejoin screen. This allows HoPs to proactively broadcast that they need more people to fill those jobs - and reduces the chance of critical crew shortages.
-
-
Purpose2 updated:
-
-
Soylen Viridians are now correctly Soylent Viridians. Nanotrasen will still not confirm rumours of the contents of these nor Soylent Greens however.
-
Nanotrasen is now more consistent with brand management.
-
An array of typos, grammatical tweaks and other pedantic fixes.
-
Adds a jobs board to the Newscaster. See what roles are available before seeing the HoP!
-
-
TullyBurnalot updated:
-
-
Autopsy Scanners will now print out Coroner Reports when a pen is used on them
-
-
alexkar598 updated:
-
-
Rename Spagetti to Spaghetti
-
-
-
13 June 2017
-
KasparoVy updated:
-
-
Moves a hidden emergency locker to where it is visible.
-
-
Vivalas updated:
-
-
Brig timers will now update the records of those who are imprisoned in their cell, as long as their name is entered correctly.
-
Sentences and arresting officers are announced over the security channel by brig timers, as well as the names of those who end timers manually.
-
-
-
10 June 2017
-
Alffd updated:
-
-
Ports Incoming5643's persistence features for Runtime from TG
-
Ports additional cat NPC emotes from TG
-
-
Citinited updated:
-
-
Disconnecting before the shuttle leaves after having spent karma will no longer prompt you to spend karma.
-
-
FalseIncarnate updated:
-
-
Adds Highlander Style, granted to the wielder of Highlander Claymores. This martial art allows you to deflect ranged attacks from the weapons of COWARDS. FOR THE HONOR OF THE HIGHLANDERS!
-
Highlander now equips combatants with a Highlander claymore instead of a normal claymore. FIGHT ON BROTHERS!
-
-
-
09 June 2017
-
Alexshreds updated:
-
-
Taking mhelps no longer gives mhelping players your IC name
-
-
FlattyPatty updated:
-
-
Added forensics gloves for the Detective.
-
-
Fox McCloud updated:
-
-
Paramedic door is no longer diamond
-
Fixes the backwards health analyzer sprite
-
Remove adrenaline and freedom implants from R&D
-
Added chem and tracking implants to R&D
-
-
KasparoVy updated:
-
-
Adds some sanity checking to the RCS.
-
The cargo shuttle no longer permits RCS telepads.
-
-
Kyep updated:
-
-
glowshrooms are now destroyable with two hits from a wirecutter.
-
New 'department' shuttle, which can be sent by CC instead of the regular evac shuttle.
-
The gods have grown tired of prayers requesting freebies, and developed some new curses with which to smite those who would treat them like miracle vending machines.
-
-
alexkar598 updated:
-
-
Surgury holosign switch has correct icon at roundstart
-
-
tigercat2000 updated:
-
-
You can now zoom in with the Set View Range option in your Preferences tab!
-
-
-
08 June 2017
-
Alexshreds updated:
-
-
Hyphema and Ocular Restoration are now possible to evolve from viruses
-
-
-
07 June 2017
-
Fethas updated:
-
-
adds cardboard cutouts..now you can trick the station into thinkings it shadowlings!
-
-
tigercat2000 updated:
-
-
Luxury versions of the bluespace shelter capsule! Currently not obtainable.
-
Black Carpet can now be crafted using a stack of carpet and a crayon.
-
Black fancy tables can now be crafted using Black Carpet.
-
Shower curtains can now be recoloured with crayons, unscrewed from the floor, disassembled with wire cutters, and reassembled using cloth, plastic, and a metal rod.
-
-
-
06 June 2017
-
DarkPyrolord updated:
-
-
Plasmamen should be able to become vampires on normal vampire rounds.
-
-
Fox McCloud updated:
-
-
adjust the mech tesla, immolator, and disabler techs to bring it in line with the tech refactor
-
-
Kyep updated:
-
-
Instagib lasers now work against non-carbon mobs, such as animals and borgs.
-
-
imsxz updated:
-
-
Sergeant Araneus now spawns at full HP.
-
-
-
04 June 2017
-
Crazylemon64 updated:
-
-
Clone's hearts now start operational
-
EMP'd clone pods can now be emptied again
-
-
FreeStylaLT updated:
-
-
Cell 6 is now connected to the atmos system properly.
-
-
-
03 June 2017
-
FlattestGuitar updated:
-
-
PACMAN boards and pico manipulators now have proper research levels
-
-
-
01 June 2017
-
Alexshreds updated:
-
-
Ian's hardsuit is no longer invisible
-
-
FreeStylaLT updated:
-
-
Gamma armory no longer affected by brig events.
-
Outer armory windoor access has been lowered to Security Officer+, instead of Warden+.
-
Removed a redundant door in the brig's main hallway.
-
Removed a redundant fire alarm, placed it elsewhere in the north hallway.
-
-
Kyep updated:
-
-
ERTs no longer start penniless, unable to afford even basic food, or coffee.
-
-
Purpose2 updated:
-
-
Adds a build-time on Tables & Racks.
-
-
tigercat2000 updated:
-
-
Upgrading the Exosuit Fabricator and Protolathe with the right parts will lower item costs
-
Added an item to Cargo that RnD can use
-
Tweaks the tech levels for many items and the required tech levels for their designs. This is to make RnD more of a station-wide effort.
-
RnD tech level skipping skips 1 level further
-
The Destructive Analyzer will only prompt the user if tech levels will not be increased.
-
The Experimentor can no longer raise tech levels of items. It can however discover the tech levels of strange objects.
-
Removes the Autolathe from the RnD Room.
-
Removed the Forensic Scanner from RnD. Cargo can order a Forensics crate now.
-
-
-
31 May 2017
-
FalseIncarnate updated:
-
-
Shrimp and electric eels properly lay their own eggs again if they have a suitable partner.
-
-
Xantholne updated:
-
-
Virologists actually spawn with their skirt
-
Coroner now can finally spawn with some Medical loadout clothes.
-
Medical Doctors will stop spawning with Chemist/Virologist Skirts
-
CMOs won't spawn with a virologist skirt anymore.
-
Virologists and Chemists wont spawn with a Medical Doctor skirt anymore.
-
-
-
30 May 2017
-
Fruerlund updated:
-
-
You can now take out pens by CTRL Clicking PDAs
-
-
-
29 May 2017
-
Jovaniph updated:
-
-
Two welding goggles on in the atmos room
-
-
Purpose2 updated:
-
-
Increases the size of Megaphones.
-
Headset encryption keys are now 'small' items.
-
-
Tayyyyyyy, FlattestGuitar updated:
-
-
A targeting mode-esque message and sound when you point at something with a gun in your active hand
-
-
-
28 May 2017
-
Fox McCloud updated:
-
-
Fixes various mobs moving around faster than intended
-
-
-
27 May 2017
-
Crazylemon64 updated:
-
-
Cloning now can be halted at any point, but ejecting too early may result in clones with missing body parts.
-
Slime people now no longer spontaneously die
-
-
-
26 May 2017
-
FlattyPatty updated:
-
-
Removes gateway hotel xeno embryo for the crew's safety.
-
-
-
25 May 2017
-
FalseIncarnate updated:
-
-
Matter Eater now requires your mouth be uncovered before you can eat matter.
-
-
Fethas updated:
-
-
PLASMAMAN ATMOS SUITS ARE NOW THE SAME AS REGULAR ATMOS SUITS FLAG WISE! AND SO IS THE CE SUIT
-
-
Kyep updated:
-
-
Fixed some mapping bugs on Centcom, e.g: shuttle medbay no longer has black walls.
-
-
Purpose2 updated:
-
-
Metastation - Adds the Paramedic's cart and locker.
-
Metastation - Adds a backup set of paramedic keys in the CMO's office.
-
Metastation - Engine no longer hotwired.
-
Metastation - Turbine doors now function properly.
-
Metastation - Toxin Mixing's Controller is now accessible.
-
Metastation - Moved Containment out a single tile, to fix irregularities with Singularity setups.
-
Metastation - Reduced redundant redundancies in the Atmos/Wiring.
-
Metastation - removed blob spawn that was only a few tiles from Cryostorage....
-
Drones can now grip Tracker Electronics & Vending Refills
-
-
Tayyyyyyy, PhantasmicDream updated:
-
-
Skrell can put a pocket sized item in their head tentacles, which can be dislodged via stunning, stripping, or death
-
Skrell can no longer have their tentacles shaved off
-
Minor grammar fix for putting stuff that's too big into containers
-
-
-
24 May 2017
-
Kyep updated:
-
-
Every head of staff now has a Department Management Console in their office. This is a very limited version of the ID console that they can use to demote people out of their departments, or move people between jobs in their department. These consoles cannot be used to hire anyone, or to accept cross-department transfers.
-
-
-
23 May 2017
-
Fethas updated:
-
-
Lockets and necklaces to the loadout. Lockets can hold paper and photos
-
Fethas fluff item
-
-
Purpose2 updated:
-
-
Adds functionality for the Atmos/Engineering Minimap to update to the right station.
-
-
-
22 May 2017
-
DarkPyrolord updated:
-
-
Rubber pellets should no longer embed.
-
Bananas fired from the staff of the honkmother should no longer embed, or be called bullets.
-
-
Kyep updated:
-
-
Adds mech-mounted variants of the existing tesla, immolator, and x-ray laser guns, with the same material and tech requirements. Admin-only Seraph mech also gets better weapons.
-
-
-
21 May 2017
-
KasparoVy updated:
-
-
Fixes a bug where only the fat roundstart disability could be selected.
-
-
-
20 May 2017
-
FlattestGuitar updated:
-
-
Adds a jobban-checking verb to the OOC tab.
-
-
KasparoVy updated:
-
-
You can now set your character's auto-accent at character creation. The verb still exists in the OOC tab.
-
-
Kyep updated:
-
-
Antag roles now have playtime requirements.
-
-
Kyep: updated:
-
-
Updated CC map.
-
-
Xantholne updated:
-
-
The Coroner now has an actual job icon.
-
-
-
19 May 2017
-
IK3I updated:
-
-
Empath stops telling you how much it hurts to not be human
-
-
MarsM0nd updated:
-
-
NanoUI map now shows the up-to-date map.
-
-
Purpose2 updated:
-
-
Coroner no longer alt title for MD
-
Adds Coroner job as its own job.
-
Adds a swanky new office for the Coroner.
-
-
-
18 May 2017
-
FreeStylaLT updated:
-
-
Added a Newscaster to Brig Toilet.
-
-
Purpose2 updated:
-
-
Adds a subtle chat-window reminder for karma on Shuttle departure. Disable/enable via preferences tab.
-
Removes the ugly round-end karma popup.
-
-
TullyBurnalot updated:
-
-
Deaf people cannot hear tape recordings anymore
-
-
-
17 May 2017
-
Fethas updated:
-
-
MORE GREY SPRITES!
-
-
FlattestGuitar updated:
-
-
You can now silence shoes just by using some duct tape on them! Shoe rags no longer exist.
-
-
Fox McCloud updated:
-
-
Neuro-toxin bar drink weakens after 13 cycles as opposed to instantly
-
-
Purpose2 updated:
-
-
Makes the new posters actually spawnable.
-
Fixes far more spelling errors than there ever should have been on the posters.
-
-
Travelling Merchant updated:
-
-
Adds a hiss emote for Unathi.
-
-
-
16 May 2017
-
FlattestGuitar updated:
-
-
Brig lockers now have radios and prisoner IDs. As per SOP!
-
-
FreeStylaLT updated:
-
-
Fixed broken disposals in brig.
-
Returned missing Sergeant Araneus to HoS office.
-
Fixed missing floor tiles in the execution hallway in Brig.
-
Remapped the entire Brig.
-
-
Kyep updated:
-
-
changed security officer job slots from 5 to 7.
-
-
uraniummeltdown updated:
-
-
You can now resist out of straightjackets
-
Straightjacketed people can be handcuffed
-
-
-
15 May 2017
-
TullyBurnalot updated:
-
-
Disposal Bin Light now works with thrown items
-
Fixes typos with cowboy items
-
-
-
13 May 2017
-
Fethas updated:
-
-
fixes a redundent add_cultist proc so cult memorize objectives works on new converts.
-
fixes an istype with IS_GAMEMODE_CULT
-
Narsie now will sometimes make a door a cult door..i thought i had that in the first time.
-
runed metal can now be only used on cult girders.
-
-
KasparoVy updated:
-
-
Fixes a sprite issue with the Unathi Dorsal Frill's webbing.
-
-
-
12 May 2017
-
Fethas updated:
-
-
Makes thrall examine use MASKCOVERMOUTH and HIDEFACE flags
-
fixes hudsunglass goof with vox.
-
-
Xantholne updated:
-
-
Changes name from dark brown to brown for the default cowboy boots
-
Gives a hint that the cowboy shirts are meant to be clipped on to your uniform
-
-
-
11 May 2017
-
Fethas updated:
-
-
Greybarber suit sprite.
-
Removes sec access from the paramedic
-
-
Fox McCloud updated:
-
-
can no longer make lethal medical patches with droppers
-
dripping reagents on someone with a dropper now incurs a 3 second delay like syringes
-
-
-
09 May 2017
-
Fethas updated:
-
-
a ton of grey clothing sprites.
-
-
-
08 May 2017
-
Purpose2 updated:
-
-
Adds a wire to the modular console on the bridge, fixing the Power Grid program.
-
-
uraniummeltdown updated:
-
-
Examine a reinforced wall for deconstruction and repair hints.
-
-
-
07 May 2017
-
GunDOSMk1 updated:
-
-
Adds Unathi cobra hood
-
-
Purpose2 updated:
-
-
Fixes the broken wiring re-electrifying the bridge window.
-
Adds the missing scrubber in Genetics holding pen
-
-
Twinmold updated:
-
-
No longer able to put grabs into kitchen equipment (deep-fried grab).
-
No longer able to put grabs inside of display cases.
-
-
-
06 May 2017
-
Allfd updated:
-
-
Thrown mobs will not step on broken glass while being thrown.
-
-
Fethas updated:
-
-
Fixes sacreficed your target not triggering the next objective.
-
YOU CAN NOW ONLY CONVERT HUMANS NOT MICE!
-
bloodspill tiles changed from base 100 (plus random number based on players) to 70.
-
Adds Tajaran veils as a loadout options
-
Racial loadout tab
-
-
LightFire69 updated:
-
-
Added a pretty plasmaman suit
-
-
uraniummeltdown updated:
-
-
Removed Robocop, Paladin, NT Default as roundstart lawsets.
-
-
-
05 May 2017
-
Fethas updated:
-
-
Magistrate, IAA, and BS will now spawn with the correct color dpet satchal and duffel
-
-
-
01 May 2017
-
Fethas updated:
-
-
There will now be an visual indicator to annouce that an incomming shuttle is about yo wreck you.
-
-
-
30 April 2017
-
scrubmcnoob updated:
-
-
Combat Shotguns now more expensive in cargo.
-
Shotgun ammo_boxes are now named and sprited as speedloaders that can speedload into a shotgun. Normal shotgun ammo boxes are just storage items for shells.
-
Adds in shotgun ammos readily available to be ordered from cargo in bulk and allows the ordering of Riot shotguns.
-
Adds in a Dragonsbreathe shotgun ammo box.
-
Tranq darts now have a sprite.
-
-
-
29 April 2017
-
FalseIncarnate updated:
-
-
Popcorn jellybeans require jellybeans to make.
-
Gum is no longer invisible, but is still very chewy.
-
-
Phantasmic Dream Art, Fethas PR updated:
-
-
Updates the shadowling sprite. Sprite by Dreamy
-
-
uraniummeltdown updated:
-
-
Examine a girder for (de)construction hints
-
Projectiles have a chance to pass through some girders
-
You can construct rough iron (false) walls with rods, wood (false) walls with wooden planks on a girder
-
Screwdriver a displaced girder to deconstruct it
-
Increased displaced girder health, decreased reinforced and cult girder health
-
False wall construction is no longer instant
-
Girder (de)construction messages should read better
-
-
-
28 April 2017
-
Alffd updated:
-
-
Adds Paperwork the sloth to cargo.
-
-
-
27 April 2017
-
Kyep updated:
-
-
Changed "suggested client version" from 510 to 511.
-
-
-
26 April 2017
-
FalseIncarnate updated:
-
-
Glowshrooms (and their subtypes) can be mass-cleared by scythes just like vines.
-
-
pinatacolada updated:
-
-
dirty surgery environments get you nasty infections
-
ghetto surgery internal organ disinfection with alcohol
-
dead limb revival surgery step
-
-
-
25 April 2017
-
Flattest updated:
-
-
Animated progress bars!
-
-
uraniummeltdown updated:
-
-
Runed girders have a clearer and bigger icon
-
Girder subtypes are properly named, "reinforced girder" and not "reinforced"
-
Summoned cult walls do not drop a girder or runed metal to prevent runed metal farming
-
Cult walls no longer have blood or human remains in them
-
Harvesters can smash more things and can summon cult walls and floors
-
Fixed not being able to make a cult wall with runed metal + runed girder
-
Runed girders will need to be deconstructed with a welder (or plasma cutter or jackhammer) instead of a wrench. Cultists can hit them with their tomes to instantly demolish them.
-
-
-
24 April 2017
-
Flattest updated:
-
-
Sleepers spit out their victims when deconstructed now.
-
-
-
23 April 2017
-
Citinited updated:
-
-
You can now fully insulate reinforced floors using a sheet of plasteel.
-
Certain floors in the turbine, incinerator, and toxins are now thermally insulated.
-
-
Crazylemon64 updated:
-
-
Reverts Norgad's east maintenance overhaul
-
-
IK3I updated:
-
-
flipping aliums now have a cooldown
-
Aliums have some more sounds to play with
-
-
Tayyyyyyy updated:
-
-
You can no longer use space pod verbs when restrained, dead, or otherwise incapacitated.
-
-
-
21 April 2017
-
Anticept updated:
-
-
Alternate Job Preference now defaults to "Return to Lobby if Preferences Unavailable". Only affects new players.
-
-
Fox McCloud updated:
-
-
Tesla can now damage blobs
-
Tesla causes machinery to overload and explode when zapping it
-
Tesla dissipates energy more slowly and is easier to charge up (making it more deadly when released)
-
Tesla will now dust mobs it bumps into
-
Tesla coils now have wires that can be pulsed to generate a tesla zap
-
-
Lady-Luck updated:
-
-
Makes several balance adjustments to existing syndicate bundles, generally making them more worthwhile.
-
Adds an Allies Cocktail object for the Bond bundle.
-
Adds the 'gadgets' syndicate bundle.
-
Removes the 'lordsingulo' and 'murder' syndicate bundles.
-
-
Spacemanspark updated:
-
-
Permits hoodies to carry flashlights.
-
-
Twinmold93 updated:
-
-
Adds attack options for deep fryers, grills, and ovens. Those breaking into the kitchen beware.
-
-
alexkar598 updated:
-
-
you can now click on things underwater
-
-
monster860 updated:
-
-
Adds an in-game way of viewing poll results
-
The player poll window automatically pops up if there is an active poll you haven't voted on.
-
Adds an browser popup for creating new polls
-
Your account needs to be at least 30 days old in order to vote on polls
-
-
-
19 April 2017
-
IK3I updated:
-
-
Chaplain now spawns with his bible
-
-
Xantholne updated:
-
-
You now correctly spawn with the CMO Skirt if selected in loadout menu
-
-
-
17 April 2017
-
KasparoVy updated:
-
-
The God-emperor of Mankind diskette's UI works again.
-
DNA UI injectors will now immediately update a person's eye colour.
-
-
Krausus updated:
-
-
You can no longer squeeze non-match objects into matchboxes.
-
-
-
16 April 2017
-
FalseIncarnate updated:
-
-
Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially.
-
Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor.
-
-
KasparoVy updated:
-
-
Adds secondary (facial) hair colours to the genome (UI). There are 6 new blocks.
-
Characters with secondary (facial) hair colours won't find they've turned black after cloning anymore.
-
-
Kyep updated:
-
-
Plasma dust no longer creates plasma gas on objects or turfs during reactions.
-
-
Twinmold93 updated:
-
-
Missing sprite for pod pilot Drask now added.
-
-
Xantholne updated:
-
-
Adds Medical Beret available via loadout menu
-
-
ZomgPonies updated:
-
-
Fixes Superhero ID cards
-
Fixes Griffin missing his Freedom Implant
-
Fixes ElectroNegmatic's Ability not working at all.
-
Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with the amount of people affected depending on how long you hold the power in for.
-
-
uraniummeltdown updated:
-
-
You can now create heat-proof glass airlocks by using a sheet of reinforced glass on the assembly during construction. Regular glass airlocks just require a sheet of glass.
-
-
-
11 April 2017
-
FalseIncarnate updated:
-
-
Damage done to the shuttle engines by a shadowling's "Extend Shuttle" ability now prevent the shuttle from being recalled to CentComm.
-
-
-
09 April 2017
-
Fox McCloud updated:
-
-
abductor glands now act as actual hearts; removing them induces heart failure
-
plasma gland no longer gibs you, but makes you vomit plasma instead
-
bodysnatcher gland no longer gibs you, but will deal brute damage instead
-
bloody gland will now drain blood instead of dealing brute damage
-
species change gland will now change your species until the gland is removed
-
adjusted the origin tech on a few gland
-
heart attacks will once again paralyse you and do slightly more brute damage
-
body snatch clones look more like their originator
-
Abductors can no longer use guns (minus their own alien energy gun)
-
Sending someone with an abductor teleport via the console will stun them for 3 cycles (doesn't apply with the advanced camera console)
-
Abductors can now purchase additional abductor vests
-
Abductors can lock/unlock vests
-
Purchasing supplies from the abductor console will no longer increase the amount of experiments you must do
-
Wonderprods will not induce sleep in those who are stunned OR sleeping
-
altered the origin tech of abductor tools
-
Can make abductor surgery tables from regular tables by adding silver sheets to an abductor table frame
-
Added a bunch more abductee objectives
-
abductors no long scream like girls
-
High capacity cells have 10,000 charge instead of 15,000
-
Mech equipment power costs minorly adjusted
-
APCs charge a bit faster
-
EMPs less effective against pods and mechs
-
Fixes not being able to recharge modular laptops/tablets
-
-
Purpose2 updated:
-
-
Welders must now been fueled and active to cut lattices.
-
-
-
06 April 2017
-
Fox McCloud updated:
-
-
Fixes autopsy report printing; print reports by clicking the device itself
-
-
davipatury updated:
-
-
Rapid Cable Layer now have an autolathe design.
-
-
-
05 April 2017
-
KasparoVy updated:
-
-
Adds a Tajaran facial hair style.
-
Adds a few new frill styles for Unathi.
-
Adds some new horn styles for Unathi.
-
Adds a couple new facial hair styles for Vulpkanin.
-
Adds a few new hair styles for Vulpkanin.
-
Updates Vulpkanin Adhara & Kajam hairstyles.
-
-
Purpose2 updated:
-
-
Can now take photos of the Blueprints to count as a completed objective.
-
Cryostorage console now stores the Null Rod & all variations.
-
Mime mech is now 'Reticence' as it should be
-
Fixes missing cult's Berserker Robe sprite.
-
Cryostorage console no longer stores hundreds of bomber jackets, and now stores hardsuits
-
Cryostorage console now catches and stores most unique objective items.
-
Corrects some typos and grammar.
-
You can now light cigarettes with Wands of Fireball, at the cost of your eyebrows.
-
-
Twinmold93 updated:
-
-
Buying poison pen will actually give you the poison pen now.
-
-
-
04 April 2017
-
FalseIncarnate updated:
-
-
Adds FullofSkittles's custom pAI sprites. Thanks FoS!
-
Custom sprites for cyborgs, AI, AI holograms, and pAI units no longer are restricted to a single name. Get your money's worth by using that borg sprite regardless of your version number!
-
-
-
03 April 2017
-
Kyep updated:
-
-
Ghosts manifested by cultists are no longer invincible, and an exploit allowing them to be made permanent has been fixed.
-
-
-
02 April 2017
-
KasparoVy updated:
-
-
Nuclear Operatives/ERT Members/Abductors will no longer spawn in with genetic quirks.
-
Thrown objects that cross a tile with non-full windows will no longer hit the window even if it isn't visually obstructing the path.
-
Shooting guns (i.e. tasers) in the above circumstances means that the taser shots won't be blocked by windows that aren't visually obstructing the path.
-
-
Kyep updated:
-
-
Adjusted Black Market Packers away mission. It now has some danger to it (carp), some more interesting stuff to find (syndi lab) and a challenge (fix the ship powergrid).
-
Slight adjustment to word lists based on our rules.
-
Removed thunderdome armor from centcom away mission.
-
Cultists now get a new sacrifice target when the current one cryos.
-
-
-
31 March 2017
-
Krausus updated:
-
-
Blobs are no longer nearly guaranteed to immediately tear themselves apart upon spawning.
-
-
Kyep updated:
-
-
Access to jobs is now based solely on Playtime, NOT days since BYOND account was registered.
-
-
-
30 March 2017
-
Crazylemon64 updated:
-
-
Cult shifter should work now
-
-
FlattestGuitar updated:
-
-
Strange Reagent only deals clone damage on a successful revival.
-
-
Fox McCloud updated:
-
-
Non-designated drinks now mix their colors from the reagents within them
-
Autopsies can now be performed without needing to cut someone open
-
Adds modular receiver to the maintenance loot system
-
Receivers can now be produced in hacked autolathes; no longer available in R&D protolathes.
-
removes the random "scary" sounds that play when walking about
-
-
KasparoVy updated:
-
-
You can now slam drinks/bottles/flasks by click-dragging them onto yourself while it's in your active hand.
-
-
Kyep updated:
-
-
The moonoutpost19 away mission should now be finishable, and more enjoyable to attempt.
-
-
uraniummeltdown updated:
-
-
Emagging a closed firelock does not permanently break it anymore, only opens it.
-
Emagged windoors should be able to be screwdriver+crowbar'd again.
-
Powered grilles now have a chance to zap you when you throw an object at them.
-
-
-
29 March 2017
-
Purpose2 updated:
-
-
'Roundstart malfunctioning' cameras now appropriately have their wires cut.
-
AI core camera can no longer be a 'roundstart malfunctioning' camera on both Box & Meta Stations.
-
-
-
28 March 2017
-
KasparoVy updated:
-
-
Skrell can now choose undergarments (undershirts, underpants, socks) at character creation and dressers.
-
Vox are now 20% less resilient to brute damage due to their light, porous and flexible skeletons.
-
-
uraniummeltdown updated:
-
-
Quick-replacing non-wooden tiles will only work with a crowbar in inactive hand instead of any item
-
-
-
27 March 2017
-
Crazylemon64 updated:
-
-
Away mission power works now.
-
-
Fox McCloud updated:
-
-
Fixes some stacks not wanting to stack with similar stacks (such as space cash)
-
-
KasparoVy updated:
-
-
Skrell have been greyscaled and darkened. You can now colour your Skrell characters as you please.
-
Kidan can now select from multiple different antennae head-accessory styles.
-
Kidan male/female bodies now have differences, namely mandible/torso structure.
-
Skrell flesh is now blue (like their blood), though you'll only ever see this under certain circumstances if they're dismembered.
-
-
Kyep updated:
-
-
The invisible floors in the engineering area of the UO45 away mission are no longer invisible. Previously, you had to crowbar up a seemingly invisible floor to make a wire appear.
-
Fixed several Terror Spider bugs. Including the notorious 'spiders can get stuck in vents' bug, the 'spiders ignore mechs' bug, and the 'prince is cheesable' bug.
-
Adjusted White & Empress spider abilities - webs spun by white spiders are now infectious.
-
-
Purpose2 updated:
-
-
Adds the Psychiatrist's bed/sofa for 5 metal.
-
Wooden chairs broken by animals no longer drop metal.
-
Abductors no longer have Syndicate ties.
-
Fixes material loss on some chair/bed/stool deconstruction types.
-
IPCs can no longer be DNA Scrambled.
-
Health analysers clunk again when upgraded
-
Resolves further grammatical/typo issues.
-
-
-
26 March 2017
-
FalseIncarnate updated:
-
-
Re-adds the telescopic scythe, the pinnacle of covert reaping technologies. Currently admin-spawn only, for use in the most dire of harvest times.
-
Scythes (normal and telescopic) should once again clear swathes through all but the hardiest of vines when in proper reaping configurations, and heavily damage those they don't outright destroy.
-
Ankle-high piles of dirt will no longer prevent you from stepping over them.
-
-
KasparoVy updated:
-
-
You can no longer climb through interdimensional rifts into cryopods.
-
Revenants can see properly in the dark again.
-
-
Kyep updated:
-
-
Adjusted Beach awaymission so it now includes deadly (but rewarding) pirate area.
-
Adjusted the centcom away mission to make it viable.
-
Deleted 'listening post' away mission.
-
-
Purpose2 updated:
-
-
QoL: Newly built APCs come unlocked.
-
QoL: Chief Engineer's locker has more building permits.
-
Assorted grammatical fixes.
-
-
Ty-Omaha updated:
-
-
Splints will display the proper sentence when applying them
-
-
uraniummeltdown updated:
-
-
Metastation: Fixed Gateway airlock access and Command Hallway vendor areas, virology smartfridge is correctly stocked, mass drivers now have tiny fans, Sec spacepod keys work on the Sec pod, Airlocks should have the correct icon, Firelocks/Windoors/Shutters should be layered correctly, Shutters should be facing the right direction
-
Drone fabricator consoles search for a fabricator in the same area instead of 3x3 range.
-
-
-
25 March 2017
-
Crazylemon64 updated:
-
-
All pens are now certified crayon-wax free!
-
-
Kyep updated:
-
-
Pipes in the Wizard Academy have been banished back under the carpet, where they belong.
-
-
-
24 March 2017
-
KasparoVy updated:
-
-
Red wire-cutters and red crowbars now appear correctly in-hands again. imgadd: The medical wrench and all the brass tools (screwdriver, crowbar, wrench, wire-cutters, welder) now have in-hand sprites of their own.
-
Adds TG's inhand icons for screwdrivers, crowbars, wrenches, wire-cutters and welders.
-
Slime People can wear underwear, undershirts and socks.
-
-
uraniummeltdown updated:
-
-
IV Drips are no longer dense objects, you can walk over them.
-
You can change gold and silver tiles into fancy versions by using them in hand.
-
-
-
23 March 2017
-
FalseIncarnate updated:
-
-
Fish breeding has been tweaked to support fish refusing to cross-breed and improved egg chances with same-species parents.
-
-
Fox McCloud updated:
-
-
Floors are now fully properly cleaned with mops and soap
-
Adds in emergency welding tool, fork, trays, drinking glasses, shot glasses, shakers, butcher cleavers, and riot darts to the autolathe
-
Adds all basic stock parts to the autolathe
-
re-arranges the autolathe menu to be more logical
-
light bulbs no longer require metal to produce
-
Incision management system can now cauterize
-
-
KasparoVy updated:
-
-
Unathi Security, Medical, Engineering and Syndicate side-facing hardsuit sprites have undergone weight reduction.
-
-
Kyep updated:
-
-
Chaplain's armor is no longer riot-grade. In addition, their nullrods do less damage.
-
-
MarsM0nd updated:
-
-
Conveyor switches can now set to left-only direction toggling.
-
-
Norgad updated:
-
-
Maintenance areas near arrivals, science, and the bar have been revamped.
-
-
uraniummeltdown updated:
-
-
Station lighting has less lighting power, this is not noticeable apart from maint and 1 bulb rooms being a bit darker.
-
Tweaked the potency scaling for glowshroom/glowberry light; high-potency plants no longer light up a huge area, but are slightly brighter.
-
Added Shadowshrooms as a glowshroom mutation. They do exactly what you'd expect.
-
-
-
22 March 2017
-
Crazylemon64 updated:
-
-
Rod form is now at half speed, and has a warning sound.
-
-
FlattestGuitar updated:
-
-
When a person's limb is dying, it will no longer notify the whole server of the ordeal
-
Welding tools no longer tell you about their span classes
-
-
KasparoVy updated:
-
-
Deconstructing beds now yields the same amount of metal as was used to make the bed.
-
The PA console will no longer appear as though it is fully constructed at the start of the round.
-
Ore Redemption Machines no longer eat IDs when deconstructed.
-
Ore Redemption Machines and Mining Equipment Vendors now spit out whatever IDs were in them when they lose power.
-
-
Krausus updated:
-
-
Personal crafting is now usable again for those with an Internet Explorer version below 11.
-
-
-
21 March 2017
-
Crazylemon64 updated:
-
-
Strange reagent now has a volume floor requirement to activate, induces clone damage, and may cause further trouble...
-
-
KasparoVy updated:
-
-
No-one escapes nuclear hellfire.
-
Secure fridges/freezers are now lead-lined and have thus become nuke resistant.
-
-
uraniummeltdown updated:
-
-
Baseball bats added to the game, are craftable from 5 wood planks.
-
Baseball burgers can be made with a baseball bat and a bun, either microwaved or table-crafted.
Fixes the exploit to produce infinite cable coil from airlocks.
-
-
Tayyyyyyy updated:
-
-
Added GPS devices to pod pilot and mechanic's offices
-
-
-
19 March 2017
-
Jovaniph updated:
-
-
Voxes can now wear soft caps.
-
-
Krausus updated:
-
-
Pest spray bottles are no longer invisible.
-
-
Kyep updated:
-
-
Wood doors in wild west map no longer constantly open/close
-
-
uraniummeltdown updated:
-
-
Shipping errors can sometimes cause the supply shuttle to receive an extra crate when ordering supplies.
-
Added dog beds! Can be made with 10 wood planks and deconstructed with a wrench. Ian's Bed added to Cyberiad and Metastation.
-
-
-
18 March 2017
-
Fox McCloud updated:
-
-
Fixes abductor surgeries
-
-
Jovaniph updated:
-
-
Unathi EVA suits
-
-
uraniummeltdown updated:
-
-
Shades now have directional sprites.
-
Attacking with glass shards now hurts your hand if not wearing gloves. Does not affect robotic hands though.
-
-
-
16 March 2017
-
FlattestGeetar updated:
-
-
Workboots are now in the loadout system.
-
Ports winter boots from /tg/
-
-
Jovaniph updated:
-
-
New sounds to Firelocks and Airlock External
-
Door closing sound to Airlocks - from yogstation
-
-
Markolie updated:
-
-
Fixed revenant night vision not working.
-
Fixed the "X attacked Y" message showing up when welding vents.
-
Fixed the follow button on the cell door timer radio message not working.
-
Fixed the Jaws of Life being unable to force unpowered doors.
-
Fixed a number of preference options being unavailable when modifying preferences while observing.
-
Fixed an issue where deleting security records wouldn't clear that player's wanted status properly.
-
Fixed the cult "first meal" sacrifice objective not counting properly. Also clarified what this objective actually entailed.
-
Fixed IPC's ocassionally being selected as a changeling "escape with X identity" target.
-
The character records and disabilities menus in the preferences menu no longer uses the plain white background, but uses the better looking blue layout instead.
-
-
-
15 March 2017
-
uraniummeltdown updated:
-
-
Plastic flaps can be deconstructed with tools and constructed using 5 sheets of plastic.
-
You can now damage grilles by throwing things at them.
-
You can rebuild broken grilles by using a metal rod on them.
-
Metal rods maximum amount reduced from 60 to 50.
-
-
-
14 March 2017
-
uraniummeltdown updated:
-
-
Strong supply talismans can now summon 5 sheets of runed metal.
-
-
-
13 March 2017
-
Kyep updated:
-
-
Syndicate mobs in the Wild West are no longer so stupid that they trip over, and die to, their own mines. This also means that they won't set their own buildings on fire anymore.
-
Phazons' phase ability now works again.
-
Phazons' toxin injector melee damage type (a weak melee attack) now works again.
-
-
uraniummeltdown updated:
-
-
Clicking on a tile with another tile and a crowbar or screwdriver in hand directly replaces the tile.
-
-
-
12 March 2017
-
Crazylemon64 updated:
-
-
Kudzu should now be less of (but still) a station-destroying force of nature.
-
Bluespace kudzu now only pierces a single layer of walls before losing its "charge".
-
Aggressive spread now does not bust rwalls, but does attack obstructing objects in its path.
-
Kudzu now only spreads on space turfs when it has specific mutations to do so.
-
Kudzu events should be more interesting on their own.
-
-
Jovaniph updated:
-
-
Adds Vulpkanin EVA suit sprite
-
-
Kyep updated:
-
-
Adjusted Wizard Academy to make it both more lethal, and more rewarding.
-
-
Markolie updated:
-
-
The system for picking ghosts to inhabit cultist slaughter demons now shows a confirmation prompt like most other role checks.
-
Fixed an issue where you could join as a cultist slaughter demon despite having antagHUD enabled.
-
Fixed an issue where it was possible to weld statues without any fuel.
-
It is no longer possible to spam the firelock force message.
-
-
Twinmold93 updated:
-
-
Employment record laptop to Head of Personnel's Office. Moves package wrap that was there to meeting room to be paired with the hand labeler there.
-
-
-
11 March 2017
-
Developed by XDTM, ported by davipatury updated:
-
-
Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
-
Added some new hallucinations.
-
Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
-
-
Flatty Patty updated:
-
-
all the tools have icons again
-
-
FlattyPatty updated:
-
-
Improved Nanotrasen click manufacturing procedures now allow the flashlights to make that classic clicking sound you know and love.
-
-
Fox McCloud updated:
-
-
Buckshot now does a max of 70 damage, down from 90
-
-
KasparoVy updated:
-
-
Fixes a bug with certain tail markings rendering when they shouldn't.
-
-
Markolie updated:
-
-
Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose if there's still an atmospherics alarm present.
-
Regular (non-heavy) firelocks will now properly respond to explosions (100% chance of being destroyed at severity 1 explosions and 50% at severity 2). Heavy firelocks are still only destroyed in severity 1 explosions.
-
Added a visible message to forcing airlocks with the Jaws of Life.
-
-
davipatury updated:
-
-
Ported Modular Computers from /tg/.
-
Ported Rapid Cable Layer from /vg/.
-
-
uraniummeltdown updated:
-
-
EVA has 2 more EVA Suits
-
Removed Vox-only EVA suits (the grey ones in EVA)
-
Vox can now wear EVA suits
-
-
-
10 March 2017
-
Jovaniph updated:
-
-
Recitence no longer makes a sound when turning
-
-
Markolie updated:
-
-
The DNA Vault station goal will now be marked as completed properly.
-
Multi-tile airlocks will now change their direction properly.
-
The atmos skirt loadout item will now be equipped properly on round start.
-
Fixes the inhand disabler sprite pointing the wrong way in some directions.
-
The Janicart will no longer act as a jetpack.
-
You can now resist out of a borer's control again.
-
Fixes the general antag ban not working on certain conversion antagonists.
-
Fixes removing the trunk from underneath a chute/bin causing all sorts of issues.
-
Fixes alt titles not showing up on ID's.
-
Mineral doors no longer block atmos (like they're supposed to).
-
Fixes the cortical borer hivemind talk not working.
-
Fixes detomatix cartridges not working *from* PDA's with an uplink (it now no longer *on* a PDA with an uplink to prevent blowing up fellow traitors).
-
Fixes NODROP interaction with secure closets.
-
Fixes some stray fruit at the Syndicate base on Z2.
-
Fixes an incorrect camera network in the courtroom.
-
Fixes an issue where AI's would go blind upon travelling into space.
-
The cortical borer hivemind talk key is now "bo".
-
Attempting to blow up an undetonatable PDA (such as the captain's) will now show a warning message. It will also no longer use up a charge.
-
Animals can now open mineral doors and mineral doors will no longer be closable if there's a mob inside.
-
Matter grippers can now carry firelock electronics as well as bluespace crystals (for construction).
-
Removes the pipe fitting on the table from atmospherics as it was broken.
-
-
-
09 March 2017
-
Crazylemon64 updated:
-
-
Adds an "ethereal beacon", an admin-only structure usable to attract ghosts to an area.
-
Adds several transformer machines to streamline the ghost-to-PC process.
-
-
LordJike updated:
-
-
Space Fries are now made by deep-frying potato wedges instead of processing them.
-
Introducing carrots inside the food processor gives you carrot wedges now.
-
Now you can make carrot fries by deep-frying carrot wedges instead of formerly processing the whole carrots.
-
-
Markolie updated:
-
-
Tools now have a "usesound" and "toolspeed" variable which allows different tool (levels) to have different sounds and speeds.
-
Robots spawn with tools that are twice as fast as regular tools.
-
Abductor agents now spawn with a toolbelt with specialized abductor tools that are very fast.
-
Abductor surgery tools are now much faster.
-
Abductor (surgery) tools can now be constructed in R&D with a sufficiently high "abductor" research level.
-
The abductor multitool will now display what each wire does.
-
Admin ghosts can now interact with wires and see what each wire does.
-
Adds a set of unique tools for the Chief Engineer that he is given in a unique toolbelt at roundstart. These tools are faster and can be created in R&D with a sufficiently high R&D level.
-
The AI detector has been refactored to have much more robust AI tracking.
-
-
-
08 March 2017
-
Alffd updated:
-
-
Farting on a bible now puts you at the mercy of the gods.
-
Removed automatic biblefarting gibbing.
-
-
FlaaaaaattestGuitar updated:
-
-
Magistrate now starts their shift with a pair of white gloves as well as Bridge and Meeting Room access.
-
-
Fox McCloud updated:
-
-
money is now far easier to use, and distribute in amounts you would like
-
-
Kyep updated:
-
-
Changed event probabilities, aiming for a more fun late game. In general, events that do very little (e.g: meaty ores, rogue drones) are less likely. Events that will keep people on their toes (e.g: anomalies) are more likely. Events that might cause people to observe rather than joining the round (e.g: Xenos) are less likely.
-
-
uraniummeltdown updated:
-
-
Wizard Hardsuit helmet and suit now have inhand sprites
-
-
-
07 March 2017
-
Crazylemon64 updated:
-
-
IPCs now come with a power cord implant to use to recharge from APCs.
-
IPCs can now be genderless.
-
-
Kyep updated:
-
-
Deleted 'challenge' away mission.
-
-
MarsM0nd updated:
-
-
Cultists get shoes on usage of the armor talisman.
-
Cultists only get equipment if they have the slot for it free, weapons are always spawned.
-
The tome does a more fitting description of the talisman of armor.
-
-
-
05 March 2017
-
Kyep updated:
-
-
Added Poison Pen, a stealthy way of applying a contact-based poison to paper. Available to Syndicate HoPs, QMs, and Cargo Techs.
-
Antags whose objectives are manually announced by an admin, or altered automatically as a result of their target cryoing, will now hear a warning sound. The sound is the same as the 'crew transfer vote called' sound. Additionally, the text notice for changed objectives is more obvious.
-
-
MarsM0nd updated:
-
-
The grey satchel uses now the correct sprite instead of the leather one.
-
-
-
04 March 2017
-
Markolie updated:
-
-
Ghosts can now interact with ore dispensers, mining equipment vendors and laptop vendors.
-
Admins can now interact with crates, closets, false walls and conveyor switches if they have advanced interaction enabled.
-
-
davipatury updated:
-
-
Newscaster now uses Nano-UI.
-
Tank dispenser now uses Nano-UI.
-
Passive gate, pump and volume pump now uses Nano-UI.
-
Atmospherics filter and mixer now uses Nano-UI.
-
Wires now uses Nano-UI.
-
-
-
03 March 2017
-
FlauntestGuitar updated:
-
-
You will now be prompted on a karma purchase to confirm that you clicked what you wanted to click
-
-
uraniummeltdown updated:
-
-
You can now change the input/output directons for Ore Redemption Machines by using a multitool on them with the panel open.
-
Bluespace RPED beams have a new sprite
-
-
-
01 March 2017
-
Crazylemon64 updated:
-
-
Kudzu vines now can yield materials if carefully tended to
-
-
Fethas updated:
-
-
2 second cooldown on the rest verb. You are not Neo, knock it off.
-
StopResting and StartResting Procs are not on the rest verb.
-
Various metastation fixes.
-
-
KasparoVy updated:
-
-
Plasmaman multiverse sword copies are now properly equipped (suit, helmet, internals, etc.)
-
Vox multiverse sword copies are now peoperly equipped (internals).
-
-
Kyep updated:
-
-
Fixed several Terror Spider things that should not be possible, like recharging wireless guns, the 'evil-looking spiderlings' instant meta, and spiderlings spacing themselves.
-
Several Terror Spider balance and fun tweaks, such as giving the Prince of Terror a new webbing ability, and ensuring queens/mothers can break open vents, so they cannot be completely shut out late-round.
-
-
Purpose2 updated:
-
-
Enables Cargo to order Wood planks
-
-
-
28 February 2017
-
KasparoVy updated:
-
-
Plasmaman suits will now only auto-extinguish if you're actually on fire (and not just taking a shower).
-
-
-
27 February 2017
-
uraniummeltdown updated:
-
-
Mineral statues are here! Use 5 sheets of any mineral including sandstone to make one. Be careful around plasma and uranium statues!
-
The mime's office now comes with a statue too.
-
Updated plasma, uranium and diamond floor sprites to TG's newer ones.
-
-
-
26 February 2017
-
Crazylemon64 updated:
-
-
Immovable rod events now vanish after going through the station once
-
Firelocks can now be operated by AIs again
-
Barbers and captains get the right stuff now
-
It's now possible to have random floors or walls when mapping
-
-
KasparoVy updated:
-
-
Fixes a bug where you could get a part of a rigsuit stuck to your hand by deploying it twice.
-
Improves the readability of some rigsuit verbs.
-
-
Kyep updated:
-
-
players will no longer spawn with loadout items their job has no access to.
-
AI & Borg upload consoles now have to be on the station zlevel to work.
-
-
davipatury updated:
-
-
ATM now uses Nano-UI.
-
-
-
25 February 2017
-
Crazylemon64 updated:
-
-
Telecomms monitor is now infused with fastitude
-
-
FlattestGuitar updated:
-
-
Escape has been re-bushed.
-
-
KasparoVy updated:
-
-
Reagent plasma has a weak healing effect on Plasmamen when injected and will not poison them.
-
Reagent oxygen is as toxic to Vox as reagent plasma is to just about anyone.
-
Plasmamen now join the shift with 2 suit auto-extinguisher refill cartridges which, individually, will fully refill an empty Plasmaman suit's autoextinguisherl.
-
Plasmaman suits now auto-extinguish and will be able to do so 5 times before they can be refilled by a cartridge.
-
Plasmamen no longer burn in a vacuum or in plasma-pure environments.
-
-
davipatury updated:
-
-
Security Records now uses Nano-UI.
-
-
-
24 February 2017
-
FalseIncarnate updated:
-
-
Corn and bananas can be properly deepfried into their special results again.
-
Rice can be properly ground into a reagent again.
-
Hydroponics trays once again are equipped with Bee-proof lids to keep unwanted pollination to a minimum. This only works if you actually toggle the lid closed though!
-
Plants age slightly slower, so your space farming should no longer feel like it outpaces a meth'd up blue hedgehog in sneakers.
-
-
Kyep updated:
-
-
Fixes blob spawns prompting players twice.
-
-
Markolie updated:
-
-
Mining pod weapons are once again functional. Compared to regular kinetic accelerators, the weak projectile has one additional range (3 --> 4). The regular projectile's damage is increased (40 --> 50) and deals more damage in pressurized environments (50% instead of 25%). The enhanced projectile is able to fire its kinetic projectile AoE against turfs and mobs.
-
Fixed an issue where it was impossible to log out from fax machines.
-
It is no longer possible to steal ID cards from identification computers/fax machine using telekinesis at range.
-
The follow link on death alarms now works.
-
Fixes an exploit where players could use the ambulance trolley to teleport.
-
The chef now properly shows a chef hat on character preview.
-
The nuclear ops game mode will no longer always result in a major crew victory.
-
Players with their face covered will no longer show their flavor text upon examine.
-
Fax machines now have an "Eject ID card" verb so you can remove the inserted ID when it is depowered.
-
Firelocks are now more lethal.
-
Firelocks now crush players standing inside them when they finish closing.
-
Firelocks can no longer be instantly opened by hand: it requires thirty seconds and will autoclose in five seconds if there is still an atmospherics alert present in the area. They can no longer be closed by hand. Heavy firelocks can not be forced by hand.
-
Atmospherics technicians can once again remotely modify all settings on air alarms through the central atmospherics console.
-
-
Purpose2 updated:
-
-
Captain's crown is now part of the random hats crate, and no longer spawns in their locker.
-
-
Twinmold93 updated:
-
-
Ability to label bloodpacks with a pen, so you can now label a bloodpack from donations without a handlabeler.
-
Bloodpacks will now change name to say if they are empty or not.
-
-
davipatury updated:
-
-
EFTPOS now uses Nano-UI.
-
Medical Records now uses Nano-UI.
-
Employment Records now uses Nano-UI.
-
-
-
23 February 2017
-
Krausus updated:
-
-
Ghost candidate alert boxes ("Do you want to play as a thing?") will now have "No" as the leftmost, default option, which you will accidentally pick when it pops up while you're trying to type, but at least you won't be stuck as the thing when you didn't actually want to be that thing.
-
-
Markolie updated:
-
-
The meteor shield satellite station goal coverage goal has been increased tenfold.
-
-
-
22 February 2017
-
KasparoVy updated:
-
-
You can now toggle on/off the gladiator helmet's face-shield with an action button. This is totally cosmetic. imgadd: Adds a bunch of new helmet sprites for Vox.
-
Slightly adjusts the Vox knight armour sprites (not the Templar armour) to look nicer with the new helmets.
-
The Admin 'Select Equipment' debug verb now appropriately equips Armalis when the 'Vox' option is selected.
-
-
-
21 February 2017
-
Crazylemon64 updated:
-
-
Autolathes can be hacked again
-
-
KasparoVy updated:
-
-
Removes rogue super-bright pixel at top of Vulpkanin Adhara hairstyle north and south facing sprites.
-
-
Kyep updated:
-
-
Deleted clown planet away mission.
-
blobs now spawn with a player in control, instantly. There is no longer a 30 second period where they exist, but nobody is controlling them.
-
blobs now get extra time after spawn, before they are announced.
-
-
Markolie updated:
-
-
Megaphones can no longer be used by mute people.
-
Rechargers will no longer recharge stacks beyond their max amount or restack 0.5 sheets.
-
Ranged guardians now have a proper one second cooldown instead of 0.1 seconds.
-
Cult can no longer soul stone manifested ghosts.
-
-
davipatury updated:
-
-
Autolathe now uses Nano-UI.
-
-
uraniummeltdown updated:
-
-
Shuttle engines should now face the correct way
-
-
-
20 February 2017
-
Markolie updated:
-
-
The chaplain on the Cyberiad map now has a one-use soulstone.
-
The chaplain's soul stone on MetaStation can now only be used once.
-
-
davipatury updated:
-
-
Shuttle Console now uses Nano-UI.
-
-
tigercat2000 updated:
-
-
The AI has a button next to radio messages to open the door closest to the speaker. ;AI, Open this fucking door!
-
-
-
19 February 2017
-
Markolie updated:
-
-
Claw games no longer eat up all glass sheets in the stack when constructed.
-
-
-
18 February 2017
-
Alffd updated:
-
-
Fixes missing entries in species/station for Vox cough and sneeze.
-
-
Crazylemon64 updated:
-
-
Centcomm has begun enforcing stricter security protocols after a recent influx of fax responses from Clown impersonators
-
Mind transfer abilities work again
-
Centcomm is no longer obnoxiously pedantic, regarding BSA deployment
-
-
Krausus updated:
-
-
End-of-round sounds will now play just in time for them to end as the server reboots, rather than starting the moment it reboots.
-
-
Kyep updated:
-
-
Added a 'take' option to ahelps/mhelps, so admins/mentors can quickly let the asker know their question is being looked at.
-
-
Markolie updated:
-
-
Vending machines, newscasters, biogenerators, plant DNA manipulators, seed extractors, bots, fax machines, photocopiers, AI slippers, cell door timers, airlocks, pipe dispensers and atmospherics machinery that open a window can now be viewed by ghosts.
-
Admins can now interact with mass driver, crematorium, ignition, light, flashers and flasher switches and door switches, as well as airlocks, windoors, firedoors and atmospherics machinery that do not open a window if they have advanced admin interaction enabled (under the "Admin" tab).
-
Slicing disposal pipes now shows a progress bar.
-
-
uraniummeltdown updated:
-
-
Shuttle engines have new sprites.
-
-
-
17 February 2017
-
Crazylemon64 updated:
-
-
Space vines now have a mutation that lets them grow in a more intelligent manner
-
-
Ported by Markolie, developed by AnturK updated:
-
-
Station Goals have been ported from /tg/. These optional goals are big projects given to the station by Central Command, requiring interdepartmental cooperation and a huge number of resources to complete.
-
Three station goals have been added: bluespace artillery construction, meteor shield satellite network and DNA vault.
-
Fixes the "Messages" tab of the communications computer.
-
-
-
16 February 2017
-
Crazylemon64 updated:
-
-
Slime people and Dionae now make sounds when coughing
-
-
KasparoVy updated:
-
-
Welding goggles and welding gas masks now properly affect your vision.
-
-
davipatury updated:
-
-
changed urnaium to uranium in wt-550 auto gun uranium magazine design
-
-
uraniummeltdown updated:
-
-
The wizard has a new spell, Rod Form, which allows him to transform into an immovable rod.
-
Ethereal beings no longer cause bananium floor tiles to squeak.
-
-
-
15 February 2017
-
Alexshreds updated:
-
-
Coughing and sneezing now plays sounds.
-
-
Ausops updated:
-
-
Internals and plasma tanks have been resprited.
-
-
Crazylemon64 updated:
-
-
Phlogiston now ignites consistently upon application
-
-
FlimFlamm updated:
-
-
New decals for boxes. Just apply a pen to change them (while they're open)!
-
-
KasparoVy updated:
-
-
You can now choose to speak anonymously in deadchat from round-start game preferences.
-
Your decision to speak anonymously in deadchat now persists between ghostings.
-
Vox tails won't change colour when other Vox spawn in anymore.
-
-
Markolie updated:
-
-
Mine bots once again only do ten damage in pressurized areas
-
-
Twinmold93 updated:
-
-
Blob Conscious Split now properly scales the requirement of blob tiles to win.
-
-
uraniummeltdown updated:
-
-
Borers now have action buttons
-
Borer names are now dependent on generation
-
-
-
14 February 2017
-
Developed by Cyberboss, ported by Markolie updated:
-
-
Progress bars will now stack vertically.
-
Progress bars will no longer be affected by lighting.
-
-
DrunkDwarf updated:
-
-
Adds a section to the Airlock menu of the RCD to allow specifying the name of the new Airlock
-
-
Fethas updated:
-
-
You can no longer put anything THAT IS ALREADY A CULTIST IN A SOULSTONE....AT ALL.
-
Readds missing beserker robe sprite.
-
Cap growth serum at 1.5
-
-
Fox McCloud updated:
-
-
Xenobiology console should be more responsive when using/exiting using it
-
Xenobiology console can now be loaded with a bag
-
Using monkey cubes on the Xenobiology console no longer makes you attempt to utilize the console
-
-
Markolie updated:
-
-
The kinetic accelerator sprite modkits now apply properly when the kinetic accelerator is empty.
-
Welding tools now once again have a proper in-hand when turned on.
-
-
-
13 February 2017
-
Crazylemon64 updated:
-
-
Achieving higher growth rates on kudzu will result in a faster-growing vine when planted
-
-
Fethas updated:
-
-
Metastation: The escape shuttle doors should no longer be security access only.
-
Metastation: Hooks up disposals door control.
-
Cyberiad: Untriggers Neca and makes the floor tiles in the emergecny wing sec area plating.
-
Cyberiad: Moves the cargo mail room table onto the otherside of the window so you can actually OPEN IT.
-
-
Fluff12 updated:
-
-
Greys can now choose to speak in wingdings or not. The Voice option is right below Species in character creation if Grey is selected - make sure you have it set to what you want!
-
-
Fox McCloud updated:
-
-
improves the tatortot sprite
-
-
Kyep updated:
-
-
Playtime requirements for IAAs have been set at 5 hours (similar to Sec Officer). Playtime requirements for Captains and AI have been increased from 10 hours to 20 hours.
-
Mech-mounted teleporters are no longer massively overpowered. They now consume a huge amount of energy to use, to the point that crew mechs with them can only use them a few times. They can no longer be spammed. Dark Gygax mechs used by nuclear operatives get a better version of the teleporter, which has around 40 uses, and is more precise.
-
Fixed several bugs related to Terror Spider webs.
-
Terror Spiders have been rebalanced. Spiders are no longer spaceproof, princes are now proper minibosses, and more.
-
Several new classes of Terror Spiders (green, white, purple, queen, mother) have been added - including types which can breed. This creates new strategy around nest defense.
-
-
Markolie updated:
-
-
Fixed a number of genetics powers not working.
-
Posibrains can no longer whisper when silenced.
-
Syndicate turrets will no longer target the Syndicate pAI found on their outpost.
-
Fixed the "Swedish" disability occasionally hiding parts of speech.
-
Mouthless players can no longer eat crayons (such as IPC's).
-
Instruments can now be interacted with while buckled.
-
Emagging a single fax machine will no longer give all fax machines access to the Syndicate destination.
-
Evidence bags will now always show the item inside of them.
-
Spacepods leaving a trail of humans instead of ion trail effects.
-
-
uraniummeltdown updated:
-
-
Nuclear Operatives can customize the Declaration of War.
-
The RSF has a unique sprite.
-
-
-
12 February 2017
-
Fox McCloud updated:
-
-
Fixes erroneous access on inner morgue door which was granting people with morgue access, access to the entirety of medical bay
-
-
Kyep updated:
-
-
added two more mining hardsuits to the mining outpost.
-
-
uraniummeltdown updated:
-
-
Whetstones have been resprited
-
Drying racks have new sprites.
-
-
-
11 February 2017
-
Markolie updated:
-
-
Ports over the remaining Lavaland loot items from /tg/ (most developed by KorPhaeron).
-
Refactors the kinetic accelerator to use modkits instead of subtypes: these unique mods (such as more range or shorter cooldown) can be purchased from the mining vendor or built by R&D or robotics (developed by KorPhaeron).
-
-
-
10 February 2017
-
Fox McCloud updated:
-
-
Fixes not being able to bloodcrawl in most sources of blood
-
Fixes slaughter demon whisper not working at all
-
Drying rack drying now properly uses NanoUI instead of a right-click verb
-
Fixes produce appearing stuck in a drying rack when it was empty
-
Fixes a few failed icon updates with the drying rack
-
-
KasparoVy, Krausus updated:
-
-
Adds the colourblindness gene. It is eye-dependent, and can be transferred from person-to-person with the eye organ.
-
Colourblindness can be detected by the advanced medical scanner just like blindness and short-sightedness.
-
Vulpkanin and Tajara can now choose to be uniquely colourblind in exchange for fantastic darksight. The default option is colour vision but low darksight.
-
Selecting mechanical or mechanically assisted eyes at character creation grants full colour vision, but standard Human darksight. This overrides the colour vision preference.
-
Mechanical(ly assisted) internal organs such as hearts and eyes are now appropriately named, and have appropriate sprites.
-
Vulpkanin and Tajara monkey-forms (Wolpins and Farwas) are incurably colourblind but have excellent darksight as they get nearly the same organs as their greater forms.
-
Increases reliability of turning into a monkey.
-
Fixes a bug with changelings lesser-forming, transforming and humanforming into a different identity.
-
-
Markolie updated:
-
-
Firelocks can now be constructed and deconstructed.
-
Firelocks no longer show a confirmation message when being opened.
-
Various map fixes (vents, scrubbers, firelocks and intercoms). Also removes the firelocks covering the windows in escape/cargo.
-
-
tigercat2000 updated:
-
-
Ported Goonstation slash /vg/ lighting. Pretty.
-
-
uraniummeltdown updated:
-
-
Quantum Pads are now buildable in R&D!
-
Quantum Pads, once built, can be linked to other Quantum Pads using a multitool. Using a Pad which has been linked will teleport everything on the sending pad to the linked pad!
-
Pads do not need to be linked in pairs: Pad A can lead to Pad B which can lead to pad C.
-
Upgrading a Quantum Pad will reduce the cooldown, charge-up time, and power consumption.
-
Quantum Pads require a bluespace crystal, a micro manipulator, a capacitor and a cable piece.
-
Events now scale better with population.
-
Enabled immovable rod, slaughter demon and morph events.
-
-
-
08 February 2017
-
Fox McCloud updated:
-
-
Grinding wheat and other products produces the proper reagents again
-
-
-
07 February 2017
-
Fox MCCloud updated:
-
-
Tank transfer valves have in-hand icons
-
Tank transfer valves with large tanks (ie: jetpacks) cannot fit in backpacks
-
-
Fox McCloud updated:
-
-
fixes xeno eggs taking damgae from disablers
-
adjusts most botany plant reagents to have "plantmatter" as opposed to nutriment
-
Blumpkins now have plasma in them
-
Fixes plant grown diona not being allied with plants and vines
-
Water coolers now dispense cups when clicking on them with a free hand
-
reagent tank dispensing amount based on the container instead of the tank
-
Fixes beaker spilling when placing a beaker into an ice cream machine
-
Adds in 100,000 unit water tanks to cargo for 12 points
-
regular water tank cost reduced from 8 to 6 points
-
Monkey cubes in boxes no longer start off wrapped
-
All monkey cube boxes at cargo are the same price
-
Fixes Nymphs not being able to cross over top of hydroponics trays
-
Diona fertilizing and weed eating is handled by clicking on the tray as a nymph rather than verbs
-
-
KasparoVy updated:
-
-
Storage implants are now checked for steal objective items.
-
-
Kyep updated:
-
-
AI holograms now transfer between holopads as the AI moves around.
-
-
uraniummeltdown updated:
-
-
Engineering and Science crates now have new sprites
-
Changelings can recall the memories of an absorb victim
-
Changelings will recall some speech of their absorb victims
-
You can now create floor tiles from minerals. Be careful around plasma and uranium floors though.
-
-
-
06 February 2017
-
Fox McCloud updated:
-
-
Fixes traitor banana peels having no sprite
-
Stunprods are constructed with igniters instead of wirecutters
-
Stunprods will spark when you stun someone with them
-
Expands the amount of cryodorm pods
-
-
KasparoVy updated:
-
-
IPC names with numbers now load correctly from SQL.
-
-
Kyep updated:
-
-
Autoprocess cloners will no longer clone people who cryo and ghost out, or otherwise deliberately remove themselves from the round.
-
Dead miners in UO45 away mission are no longer naked.
-
ERT and SST shuttle consoles now require the appropriate access to use.
-
-
uraniummeltdown updated:
-
-
You can interact with an ore box by using an advanced mining scanner on it.
-
Xenobiology Console is now constructible, board has been added to the Circuit Imprinter.
-
Plasmaman IAA/Lawyers now have a unique suit.
-
AI control beacons are a new item created from the exosuit fabricator. When installed into a mech, it allows AIs to jump to and from that mech freely. Note that malfunctioning AIs with the domination power unlocked will instead be forced to dominate the mech.
-
Changelings have a new default ability: Hivemind Link. This lets you bring a neck-grabbed victim into the hivemind for a few minutes. You can talk to your victims and perhaps persuade them to help you, give you intel, or even a PDA code. Victims in crit will be stabilized.
-
Added new AI core sprites from TG
-
Added Vox rad suit, bombsuit hood, paramedic EVA suit sprites from /vg/
-
You can click AI displays as an AI to change them
-
-
-
05 February 2017
-
Fethas updated:
-
-
Brings unholy water in line with its description.
-
-
Fox McCloud and Core0verload updated:
-
-
Dramatically overhauls the botany system; features more user friendly gene modification methods, more control over attributes and reagents in your plants, and more
-
Adds in drying rack for drying growns for smoking with rolled papers
-
Store spare seeds in the seed extractor
-
Adds in cloth; make clothing, satchels, backpacks, duffelbags and more.
-
Upgrading hydroponics trays impacts how quickly plants degrade
-
Bees slightly more effective at increasing plant yields
-
Overall growth rate of plants dramatically increased
-
Adds in the ability to construct bonfires with wooden logs; perfect for keeping you our your fellow spessman warm---forever
-
Adds in a few new bartender drinks and recipes, such as chocolate pudding, vanilla pudding, and pumpkin spice
-
Can now wear some flowers/ambrosia in your hair
-
Combining genes form different plants has unique effects (For instance, the battery gene with the recharging gene allows you to make insanely potent batteries)
-
Vines are now purely handled by the Kudzu plant
-
Botanists have been given morgue access
-
-
Ported by Markolie, developed by KorPhaeron and others from /tg/. The Hierophant was developed by ChangelingRain. updated:
-
-
Megafauna and their rewards have been added to the code. These are not on the map yet.
-
Fireball is now a targeted spell instead of a dumbfire spell.
-
Most spells, wands and staffs now have unique spell sounds.
-
Added a new nullrod type, the "spellblade".
-
Added bows, arrows and quivers. Currently only available for admins.
-
Added cockroaches. Currently only available for admins.
-
Added support for BYOND medals. Currently disabled.
-
Added a number of Lavaland objects (flora, basalt, food and stacks). Currently only available for admins.
-
Earmuffs can now be produced in autolathes.
-
Syndicate gun turrets are now subtypes of regular turrets: this makes them controllable with Syndicate ID's and improves their targeting.
-
Diona and Shadow People now receive a warning when they're not exposed/exposed to light.
-
The sniper AP rounds that Nuke Ops can purchase now have a chance of dismembering limbs.
-
Shadow People can now switch their night vision properly.
-
Certain messages in chat weren't showing up in their proper (large) size, such as the Nar'Sie spawned message. This has been resolved.
-
-
uraniummeltdown updated:
-
-
Supply ID skin is now selectable in the Agent ID and ID Computer
-
-
-
03 February 2017
-
DrunkDwarf updated:
-
-
Set the Mr Chang's vending machine to be refillable
-
Added a Supply Crate to the Vending section of the Cargo Request Console for Chinese Refill Canisters
-
-
-
02 February 2017
-
Alexshreds updated:
-
-
Deconstructing closets yields the proper amount of metal
-
-
Kyep updated:
-
-
Using the 'summon narsie' rune as cult, when you don't have the objective to do so, is now punished by the cult's god. Just as using the 'call forth the slaughter' rune, when you don't have the objective to do that, is already punished.
-
-
uraniummeltdown updated:
-
-
Engineering Cyborgs now have a digital copy of the station blueprints.
-
-
-
31 January 2017
-
Ar3nn updated:
-
-
cursed cluwne mask now allows internals to be fed through it
-
-
FalseIncarnate updated:
-
-
All requests consoles can print off a single-use, pre-tagged Shipping Package for sending a single item via disposals to a destination of your choosing.
-
Shipping Packages can be used to tag packages wrapped with wrapping paper, in case you don't have access to cargo's destination tagger.
-
Requests Consoles log the printer and destination of all shipping labels printed from that particular console. There currently is no way to clear your mailing history, so mail responsibly.
-
-
Fethas updated:
-
-
Fixes a rune runtime.
-
-
FlattestGuitar updated:
-
-
adds an admin-only laser carbine
-
-
uraniummeltdown updated:
-
-
Your game window will now flash on receiving Admin PMs, being revived, and ghost roles. You can disable this in Game Preferences.
-
-
-
30 January 2017
-
Alexshreds updated:
-
-
No more double traitor 241 Special
-
-
-
29 January 2017
-
uraniummeltdown updated:
-
-
You can now take items directly out of a storage item in your backpack.
-
-
-
27 January 2017
-
Alffd updated:
-
-
Adds missing hat and shoe sprites that were inadvertently deleted.
-
-
Fox McCloud updated:
-
-
Adds in stungloves (inaccessible to players)
-
-
uraniummeltdown updated:
-
-
Injecting a rainbow slime extract with blood will create a consciousness transference potion.
-
Injecting a metal slime extract with water will create 15 sheets of glass and 5 sheets of reinforced glass.
-
Slime potions now check for proximity.
-
-
-
26 January 2017
-
FalseIncarnate updated:
-
-
Plasma dust can now be used to rig lights and power cells, like the plasma reagent, with explosive results.
-
-
Fethas updated:
-
-
Adds two new holy weapon skins for people who belive in ghosts and worshipers of the silentfather.
-
-
FreeStylaLT updated:
-
-
AI sat transport tubes are no longer misaligned
-
-
-
25 January 2017
-
FlattestGuitar updated:
-
-
Fixes shadowlings thrall scaling
-
-
scrubmcnoob updated:
-
-
Shadowling Thrall count now scales to a max of 25.
-
Shadowling Thralls lose lesser glare
-
-
-
23 January 2017
-
FalseIncarnate updated:
-
-
Returns the ability to remove vacant soil with shovels and spades, and adds the ability to dig up plants in soil to remove them instantly.
-
-
Stratus updated:
-
-
NT Enforcer .45 pistol.
-
.45 and 9mm rubber bullets.
-
New shotgun ammo boxes.
-
-
-
18 January 2017
-
AndriiYukhymchak updated:
-
-
multitool can now be used to swap directions of TEG's circulator
-
-
Fethas updated:
-
-
Adds in the check numbers proc to converting, I missed it from VG.
-
Removed a redundent sacrefice objective check AND fixed the sacrfice objective check so it actually PICKs on mode start.
-
changed the color of manfested ghost humans to grey...huehuehuehuehue(serously it helps tell them apart better).
-
mass convert objective now picks between 9 and 15 as a target instead of based on round pop..cuase 30 MIGHT be a bit much.
-
adds admin cult tools Bypass phase (missed this off vg) and cult mind speak(YOUR GOD IS DISPLEASED GIT GUD). Might be better in secret panel but it confuses me.
-
Removes errent invisaible animals from the narnar escape shuttle template.
-
-
KasparoVy updated:
-
-
Characters with the obese disability are now fat beneath their clothes.
-
-
Markolie updated:
-
-
Admin announcements are no longer sent to player in the lobby.
-
Regular announcements can now only be heard if you the player is alive, not deaf and in range of an enabled radio.
-
-
-
17 January 2017
-
Crazylemon64 updated:
-
-
Joined Souls works now
-
Scribing the end rune now no longer is impossible
-
-
Krausus updated:
-
-
Fixed the exciting new emoji breaking chat entirely for IE8 users. :clap:
-
-
-
16 January 2017
-
Alexshreds updated:
-
-
Revenants can now breathe in space.
-
Can no longer exploit RCDs for metal
-
-
Krausus updated:
-
-
You can now use pills and patches on people with full bellies.
-
The Randomized Character Slot option now actually works.
-
-
-
15 January 2017
-
Funce updated:
-
-
dual-port air vents can now be unwrenched
-
-
TullyBurnalot updated:
-
-
Broken and Burned bulbs are no longer forced on with every overload.
-
Only non-broken and non-burned bulbs actually break and spark on an overload.
-
Fixes a single syntax error in the Shadowling Ascendant descriptive text.
-
-
-
14 January 2017
-
Crazylemon64 updated:
-
-
Bibles can now reveal runes as they did before
-
-
Krausus updated:
-
-
Players will no longer be informed of what cult may or may not exist on round start.
-
-
-
13 January 2017
-
DarkPyrolord updated:
-
-
Removes the joy mask
-
-
TullyBurnalot updated:
-
-
Cyborg tools (and other non-droppable tools) cannot be transferred to an open, empty Display Case
-
Jobs receive links to SOP and their Department SOP at roundstart. Space Law and Legal SOP links added to Security members, Magistrate and IAAs
-
-
uraniummeltdown updated:
-
-
You can see what sting you have equipped as changeling.
-
All species except IPCs can now be changelings and be affected by their genetic abilities.
-
Arm Blade can now pry open powered airlocks
-
Transformation Sting now costs 3 points and requires 50 chemicals
-
You can no longer transform people into Vox with Transformation Sting.
-
Removed Engorged Chemical Glands, Changelings now have the ability by default
-
-
-
12 January 2017
-
TullyBurnalot updated:
-
-
Graffiti now have hidden (Admin-only) fingerprints added to them
-
-
-
11 January 2017
-
Crazylemon64 updated:
-
-
Ghosts can now see if they're allowed to respawn or not at a glance
-
Cyborg sight modes are now actions, instead of items
-
Mining drones can now use meson sight again
-
It's no longer opposite day for the karma reminder preference
-
-
Lady Luck updated:
-
-
office laptops are now traversable
-
-
Markolie updated:
-
-
simple_animals now have an attack cooldown when attacking mechas.
-
-
uraniummeltdown updated:
-
-
Atmos Console Boards now show in Computer Boards of Circuit Imprinter
-
-
-
10 January 2017
-
Crazylemon updated:
-
-
Giant spiders now have their own role pref
-
-
Crazylemon64 updated:
-
-
pAIs can now adjust their radios
-
pAIs can now more reliably hear nearby whispers
-
pAIs can now whisper while inside a PDA
-
pAIs can no longer change their icon from being dead, while dead
-
Non-respawnable players are no longer prompted to submit a pAI when the opportunity is available
-
Borg sight modules work again
-
-
Fox McCloud updated:
-
-
different alert levels for how full you are from starving all the way to fat
-
There is now satiety and nutrition; being satisfied and full has a number of positive benefits; being unsatisfied and hungry has negative side effects
-
Some foods have vitamins in them which provide little nutrition, but greatly increase your satisfaction
-
Some food reagents have had their nutritional values tweaked
-
reagent numbers tweaked on most food items
-
Fixes the floral gun not properly working on Diona
-
-
TullyBurnalot updated:
-
-
Wand of Death now reliably kills people by adding 300 Burn Damage. This includes self-casting
-
Minor flavour text visible on impact of target
-
pAI HUDs are now visual-only, restricting their access to editable records
-
-
pinatacolada updated:
-
-
IV drips now have adjustable rates
-
-
uraniummeltdown updated:
-
-
Mimes can now choose name on entry just like Clowns
-
Added many new costumes to the Autodrobe!
-
-
-
09 January 2017
-
Crazylemon64 updated:
-
-
The operating table now checks for both either `lying` or `resting` - so surgery will work no matter what on unconscious people lying on your table.
-
-
Kyep updated:
-
-
Antags should no longer get bounced to lobby at round start in certain rare situations.
-
-
-
07 January 2017
-
Markolie updated:
-
-
False walls now block atmospherics, unless it's open.
-
-
-
06 January 2017
-
Crazylemon64 updated:
-
-
pAI UIs no longer break
-
The chem dispenser's UI now displays the remaining energy again
-
Shuttles no longer make buckling useless
-
You should no longer go mute randomly
-
You can now opt out of all requests on a role for a round
-
Morgue trays now have descriptions that correspond to each of the morgue light states
-
Waking up no longer auto-cancels resting.
-
-
Fethas updated:
-
-
ports parts TG neo-oldcult rscadd:Ports parts of cult from VG
-
-
KasparoVy updated:
-
-
Grey sprites have been tidied up and no longer have any random pixels hanging off.
-
Grey species-fitted tattoo sprites and the last Vox species-fitted tattoo sprite.
-
-
Krausus updated:
-
-
SDQL2 can now directly manipulate clients.
-
-
Kyep updated:
-
-
Mobs in vents no longer see vents/scrubbers as unwelded when they are welded, and vice versa.
-
-
-
03 January 2017
-
KasparoVy updated:
-
-
The Vulpkanin Anita hairstyle no longer has rogue extra-bright pixels.
-
-
Kyep updated:
-
-
Added tracking for how much playtime each player has.
-
Added the ability to lock jobs based on playtime. E.g: must play for 10 hours to unlock HoS.
-
-
-
02 January 2017
-
KasparoVy updated:
-
-
Particle Accelerators ordered from Cargo can now function.
-
Wrenching powerless machines in a powered area will no longer require you to toggle the lights (or whatever you did before to sort this).
-
-
Krausus updated:
-
-
The syndicate nuke and pinpointer locker will once again spawn into their ship, rather than into space near the station.
-
-
Kyep updated:
-
-
Terror Spiders can no longer create more than one web on a tile.
-
-
-
01 January 2017
-
Kyep updated:
-
-
Added basic, AI-less versions of some Terror Spiders.
-
-
-
31 December 2016
-
Crazylemon64 updated:
-
-
The home gateway now will send ghosts to the other end by default, now
-
-
-
30 December 2016
-
Crazylemon updated:
-
-
The shuttle manipulator can now only be used by admins
-
-
FalseIncarnate updated:
-
-
Adds Nano-Mob Hunter GO! PDA game cartridges and related stuff. Grab a cartridge from the cartridge vendor or loadout and join in on the hunt!
-
Adds Nano-Mob Hunter GO! Battle Terminals to the Holodeck and a Nano-Mob Hunter GO! Restoration Terminal to medbay's lobby.
-
-
Fox McCloud updated:
-
-
Fixes cyborg cryo oddities
-
-
KasparoVy updated:
-
-
Taking off noir glasses while noir mode is on will now give you your colour vision back.
-
-
-
29 December 2016
-
Fethas updated:
-
-
Alternate shuttle/ferry template system from TG
-
Shuttle Manipulator
-
Better shuttle kills
-
-
Markolie updated:
-
-
The camera console has been refactored so there's no longer a delay when switching cameras.
-
The camera console should no longer lag for several seconds.
-
-
-
25 December 2016
-
FalseIncarnate updated:
-
-
Santa's back and with-holding all your presents! Head through the gateway and show the Fat Man the strength of your holiday spirit (and advanced weaponry, you'll be needing that)!
-
-
KasparoVy updated:
-
-
Cameras will no longer be able to take photos of stuff outside your line of sight.
-
Cameras will now render disguises as you see them.
-
-
-
23 December 2016
-
Crazylemon64 updated:
-
-
Welding overlays now update instantly
-
Being inside various structures will now obscure your vision
-
-
Fox McCloud updated:
-
-
Fixes X-Ray not doing anything
-
Fixes nightvision not granting what its name implies
Characters will now be correctly assigned their species' genetic quirks at spawn.
-
Cloning will now correctly assign a characters species' genetic quirks.
-
Changing a character's species (via C.M.A. or whatever might call the set_species proc) will now correctly assign their species' genetic quirks.
-
-
Markolie updated:
-
-
Ruins no longer trigger power alarms.
-
-
-
20 December 2016
-
TullyBurnalot updated:
-
-
Neurotoxin Spit now causes the spitter to move in space
-
Proximity Wet Floor Sign Mines can no longer appear in Surplus Crates
-
-
-
14 December 2016
-
Fox McCloud updated:
-
-
Fixes the personal crafting cost of ED-209's being too expensive
-
-
-
13 December 2016
-
TullyBurnalot updated:
-
-
Medbots no longer run after injured mobs if buckled. They also inform nearby players of this
-
-
-
12 December 2016
-
Kyep updated:
-
-
Xenomorph resin walls no longer take damage from disabler beams. Only proper BRUTE or BURN damage hurts them now.
-
-
TullyBurnalot updated:
-
-
Throwing mobs behind you force moves them to behind you before actually throwing them, preventing throw-shoving
-
-
-
09 December 2016
-
KasparoVy updated:
-
-
You can now define whether a hair style will cover glasses or not. Only long hair styles should cover glasses (default behaviour).
-
You can now define whether a facial hair style/head accessory will be rendered on top of hair or not.
-
Glasses no longer render on top of all hair styles, only sufficiently short ones.
-
-
-
08 December 2016
-
Kyep updated:
-
-
Ensures cryo pods will properly auto-eject people whose organic parts (limbs) have been healed, but who still have damaged mechanical limbs.
-
Disabler shots no longer damage mechs.
-
On impact, both taser and disabler shots now produce a message saying that the mech is undamaged by them, instead of a message saying they 'hit'.
-
Fixed runtimes created when SIT, ERT, and some other mobs are spawned.
-
Fixed a bug causing SITs to be spawned with one less person than desired in some cases.
-
-
-
07 December 2016
-
Markolie updated:
-
-
Verbs have been cleaned up: all karma verbs can now be found under "OOC" instead of "Special Verbs". Most admin verbs have been moved out of "Special Verbs" as well.
-
-
TullyBurnalot updated:
-
-
Unpowered Mining Vendors no longer accept IDs
-
Ore Redemption Machine and Mining Vendor can now be deconstructed if unpowered
-
-
-
06 December 2016
-
Markolie updated:
-
-
The track button on the AI crew monitor now works.
-
Permanent door electrification by alt-clicking a door as an AI or setting it manually now works again.
-
-
-
05 December 2016
-
KasparoVy updated:
-
-
Resolves an issue where cloned vampires could no longer drain blood, burn in the chapel or use their powers properly.
-
-
-
04 December 2016
-
KasparoVy updated:
-
-
Resolves an issue with changeling regenerative stasis where changelings who initiated it while alive and died during the waiting period did not come back to life. Now they will, as intended.
-
-
-
03 December 2016
-
Kyep updated:
-
-
the anti-ERP warning message on PDA message consoles is now accurate.
-
-
-
01 December 2016
-
Crazylemon64 updated:
-
-
Cryo tubes no longer let you excessively multiply the efficiency of touch chems
-
-
KasparoVy updated:
-
-
The character preview icon in character creation is now more detailed and less blurry.
-
ID cards now show tails, body accessories and tail markings correctly.
-
-
Twinmold93 updated:
-
-
Pilots of spacepods will no longer be sent to the void when the space pod is destroyed in any method.
-
Pilots of spacepods will now get the same warnings for damage/core destruction that passengers get.
-
-
-
29 November 2016
-
KasparoVy updated:
-
-
Head, body and tail markings are now loaded correctly from genes (UI).
-
Changes to a person's skin-tone gene are now immediately apparent.
-
-
-
28 November 2016
-
Allfd updated:
-
-
Fixes an issue with the processing of GitHub changelog emoji in the php webhook.
-
-
Crazylemon64 updated:
-
-
The RCD no longer shall work as a remote permissions control
-
-
KasparoVy updated:
-
-
Pressing the light switch in one OR will no longer turn off the lights for both.
-
The fire alarms in each OR now work independently of each-other.
-
The second operating room now has its own APC and wiring.
-
-
-
26 November 2016
-
Fox McCloud updated:
-
-
Fixes faint emote doing nothing
-
Fixes Mickey Finn's Special Brew not functioning properly/not making you fall asleep
-
-
-
23 November 2016
-
Fethas updated:
-
-
Fixes human jetpacks..maybe...
-
-
FlattestNerd updated:
-
-
the e20 will now get logged when it goes BEWM, as it should.
-
-
Fox McCloud updated:
-
-
Fixes double-breaking news newscaster
-
-
-
22 November 2016
-
KasparoVy updated:
-
-
You now stutter when you're in shock/crit and when you've got the nervous disability as you used to.
-
-
Twinmold93 updated:
-
-
Runtime caused by lack of settlers in the Orion arcade game.
-
-
-
20 November 2016
-
KasparoVy updated:
-
-
The DNA SE injectors one can find in the abandoned mining crates now correctly activate/deactivate the powers they may contain.
-
-
-
15 November 2016
-
KasparoVy updated:
-
-
Adding cable to multiple computer frames at the same time while not having the correct amount of cables will no longer cause busted coils with a negative number of cables.
-
-
-
13 November 2016
-
Fox McCloud updated:
-
-
Fixes BSA having peculiar results.
-
-
-
07 November 2016
-
Crazylemon updated:
-
-
Status effects should work a little more consistently now
-
-
Crazylemon64 updated:
-
-
The mech-mounted plasma cutter can now be constructed again
-
Space pod lasers can now be constructed again
-
-
Fox McCloud updated:
-
-
Fixes hunters not being weakened when crashing into a shield/wall
-
Fixes xeno stuns half the time intended
-
Fixes stopping, dropping, and rolling not properly weakening Xenos/Hulks
-
-
KasparoVy updated:
-
-
Fixes a bug where changing your alt head required two icon updates to show.
-
Fixes a bug where you couldn't choose head marking styles that would ordinarily be available regardless of your alt head.
-
Fixes a bug where Tajara couldn't choose undergarments.
-
Resolves an issue with the Vulpkanin Jagged hairstyle missing a pixel.
-
-
Twinmold93 updated:
-
-
Fixes a runtime issue caused by using the detective's scanner on the space hotel cleaver.
-
Scrubber pipe missing segment behind the operating theatres.
-
-
-
23 October 2016
-
KasparoVy updated:
-
-
Refactors markings. Now split into head, body and tail markings.
-
Refactors morph again. Changes made while morphing are now reflected instantly on your sprite.
-
Darkens Vulpkanin and Tajara for improved colour fidelity. Species base colour changed to compensate. Add 27 to R, G and B values if Vulp, 15 if Taj to keep the same colour on your character.
-
Darkens Vulpkanin facial fur patterns for improved colour fidelity. Add 23 to the R, G and B values of your facial hair/head accessory to keep the same colour on your character.
-
Darkens Unathi frills and horns. Add 27 to the R, G and B values of your frills and 21 for horns to keep the same colour on your character.
-
Vulpkanin tails are now split-rendered. Tails overlap hair when facing north, but are overlapped by hair when facing all other directions. No other differences, only affects the fluffy husky tail.
-
The heads of tiger markings have been isolated and can now be coloured independently.
-
Hair can now cover facial hair, and glasses are no longer covered by facial hair and head accessories. Means that two-piece Vulpkanin facial fur patterns won't almost entirely cover whatever glasses they're wearing.
-
Tajaran head and facial hair have been darkened. Add 28 to the R, G and B values of your Tajara head/facial hair to keep the same colour on your character.
-
Vulpkanin head hair and one facial hair style has been darkened. Refer to PR notes for darkening factors.
-
The HAS_MARKINGS flag now represents all marking locations. The HAS_location_MARKINGS flags are for specific locations (head, body, tail).
-
Improves the quality of some Vulpkanin/Tajara/Unathi mask sprites.
-
Naked Humans and Skrell will no longer have exposed flesh poking out their wrists when facing east or west. Male Humans now no longer lack a butt pixel when facing east or west.
-
Mutated limbs now render correctly as soon as they're mutated.
-
Mobs will now correctly appear as fat/skinny.
-
Species with TAIL_OVERLAPPED will no longer wag tail at max speed when facing north.
-
Species with TAIL_OVERLAPPED and body accessories won't crash the game when they wag.
-
Tiger Head and Face markings adjusted so they don't look ugly on certain species' ears.
-
Fixes issue where Unathi dorsal stripe didn't render.
-
Tajaran ears are no longer in their hair sprites, but on their actual heads.
-
The adminbus body accessory now overrides the TAIL_OVERLAPPED flag and will now be rendered correctly on a body regardless of species bodyflags.
-
Changing a person's species via CMA will no longer result in a mob with all the same cosmetic attributes as the old species.
-
Dressers now have species fitting checks for undergarments. Drask are now able to wear undershirts and underwear like they were originally meant to.
-
Adds some head markings for Tajara and Vulpkanin.
-
Adds body marking(s) for Tajara, Vulpkanin, Unathi and Drask.
-
Adds tail markings for Vox and Vulpkanin.
-
Adds 5 Tajaran hairstyles.
-
Adds a tweaked version of an existing Vox hairstyle. Shouldn't clip with certain jackets as much.
-
Adds a hairstyle for Humans, Unathi and Vulpkanin.
-
Adds a facial hairstyle for Vulpkanin.
-
Adds secondary hair (head and facial) themes. Skrell can now colour their tentacle cloths independently, the beads in the Tajaran/Hippie braid hairstyles can be coloured and the same with the webbing in Unathi frills. Can be changed at nanomirrors, via morph and CMA.
-
Adds alternate heads. Unathi can now choose a head with a sharp snout. Can be changed via morph and CMA.
-
Helper procs to convert a hex colour into either R, G, or B.
-
Markings, body accessories, head accessories, alt heads and their colours (if they have colours) can now be randomized at the character preferences screen.
-
Adds a system that attempts to fit mobs with alternate heads with appropriate mask sprites. The sprites just need to be suffixed with the alt_head suffix in sprite_accessories.dm.
-
Adds mask sprites tweaked to fit the new Unathi alternate head to go along with the new alt. head mask fitting system.
-
-
-
15 October 2016
-
Crazylemon64 updated:
-
-
The R&D console should now no longer freeze on the "Syncing Database" message or whatever.
-
Borg coolers and SMES boards can be made again
-
Maroon now works
-
-
FlattestGuitar updated:
-
-
pAIs no longer turn into debris when wiped
-
SNPCs no longer get targeted by assasinate objectives
-
fixes a hallucination runtime, actually making one more aspect of being high as f*** work for the first time in ages
-
NODROP items will no longer attempt to be dropped if your hand is broken
-
-
Fox McCloud updated:
-
-
Cloners will now put you inside the cloned body when it is fully grown as opposed to initially created
-
Examining a cloner will tell you the clone progress
-
Observers can now see a visual countdown of the cloning status progression
-
Atmos grenades cost increased from 6 to 11
-
Mice now have sprites when worn
-
Fixes various ghost alerts having barely visible icons
-
Fixes items being in two locations at once when loading things into the bio-generator or reagent grinder.
-
-
GeneralChaos81 updated:
-
-
Ability to place and remove conveyor belts and levers.
-
-
KasparoVy updated:
-
-
Botany, viro and xenobio bottles will no longer be invisible.
-
-
Krausus updated:
-
-
Fixed full chat panes scrolling unpredictably when trying to view old messages.
-
Fixed camera monitors immobilizing you if you reconnect while using one.
-
Fixed selecting datum types through SDQL2 never returning any datums.
-
-
-
16 September 2016
-
Aurorablade updated:
-
-
*fart now has newtonian move if you have the Superfart power
-
-
Coldflame updated:
-
-
Adds three new variants of 10mm ammunition, AP, HP, and Incendiary. Currently admin-only.
-
-
Crazylemon64 updated:
-
-
Research data disks now have a description and name attached to them automatically, to make working with them less obnoxious.
-
Loading design disks now has a sound effect.
-
You can no longer feed non-design disks into the autolathe and destroy them on accident.
-
-
DaveTheHeadcrab updated:
-
-
Due to budget cuts expensive fax machines have been replaced with cheaper versions in some departments. Only essential personnel can fax Central Command. See your local IAA for details.
-
-
FlattestGuitar updated:
-
-
Added emergency nitrogen and plasma tanks, you can find two of each in the medical storage
-
-
FreeStylaLT updated:
-
-
Updated Metastation's AI Sat, brig and escape shuttle
-
Updated other Meta areas to match most recent build. (Chapel, some maint, etc. - minor changes.)
-
Updated Cyberiad's AI Sat to latest tg version, lots of changes there - basically an entirely new Satellite.
-
-
IcyV updated:
-
-
Adds new bottle sprite
-
Fixes many bottles being locked to a single icon
-
Buckets can be worn as hats.
-
-
Improvedname updated:
-
-
Adds 4 epinephrine autoinjectors to nanomedplus vending machines
-
-
KasparoVy updated:
-
-
Adds a Science departmental beret that you can obtain via the loadout system.
-
-
Krausus updated:
-
-
Fixed species-restricted items sometimes failing to "equip" to restricted species' non-equipment slots.
-
Players using very old versions of Internet Explorer will now receive explicit warnings that they're not supported.
-
View Variables will now consistently view the variables of what it's intended to.
-
Admins can now use the 'msay' command to speak directly to all mentors.
-
Added a new command, "Toggle Mentor Chat", to give mentors temporary access to 'msay'.
-
Fixed never being able to properly respond to a PM from a stealthed admin.
-
-
Kyep updated:
-
-
SST and SIT now have their own radio frequency.
-
-
LittleBigKid2000 updated:
-
-
The God Emperor of Mankind disk now works properly
-
-
TheDZD updated:
-
-
Xenomorph hunters' leap ability is now always blocked by shields rather than only 50% of the time.
-
Xenomorph hunters' leap ability being blocked now stuns them as if they had hit a wall. The leap still goes on a 3 second cooldown as normal.
-
-
Ty-Omaha updated:
-
-
Adds fluff item "Tacticool EyePro"
-
-
-
01 September 2016
-
Crazylemon updated:
-
-
Dying of low blood is no longer capable of causing eternal death
-
Having your body brought back to life will no longer break your health doll
-
-
monster860 updated:
-
-
Fixes hotel SNPC's getting access that they shouldn't get.
-
-
-
29 August 2016
-
Crazylemon updated:
-
-
You can now mend incisions after having cut open someone's ribcage.
-
Abductor surgery works again
-
Face repair surgery works again
-
The `to_chat` messages are now more descriptive when given a bad target
-
Admins can now VV by a ref string, directly via a verb
-
VV now builds its HTML using lists, making it much faster to open
-
-
DaveTheHeadcrab updated:
-
-
Upgrades the newscaster's liquid paper printing apparatus. Newspapers printed are higher quality now.
-
-
Fox McCloud updated:
-
-
Mining Drones can now toggle meson vision on or off, a light, switch attack modes, or even drop their own ore
-
Ash storms no longer impact sheltered areas and mining mobs are immune to ash storms
-
Adds in two new end-round sounds
-
Fixes drones not being able to bump open doors
-
-
Fox McCloud and KorPhaeron updated:
-
-
Adds in mining shelters
-
Adds in a few more dice types and ensure dice are packed in bags and not pill bottles
-
-
FreeStylaLT updated:
-
-
Added additional coating to Turbine room.
-
Fixed leftover vent in Brig Physician's office
-
Fixed missing coated rwalls in Incinerator
-
-
Krausus updated:
-
-
Girders are no longer bulletproof.
-
Changelings' Swap Form ability now actually deducts its cost upon use, and shouldn't arbitrarily fail to work properly.
-
Fixed setting status display alerts through communications consoles.
-
-
Kyep updated:
-
-
Fixes 'SSD!' warning appearing in attack logs for admins, when the target player was dead and had ghosted out of their body
-
-
TheDZD updated:
-
-
Bookcases no longer force you to take out a book after clicking them
-
Fixes assorted things logging attacks incorrectly.
-
-
TullyBurnalot updated:
-
-
AIs can no longer interact with nuclear bombs (Syndicate-brand included). AIs can still see the countdown
-
Mobs without appendixes can no longer contract appendicitis
-
Holosigns cannot be pulled around
-
-
-
19 August 2016
-
Crazylemon updated:
-
-
pAIs should now save
-
-
FalseIncarnate updated:
-
-
Repairing burn damage to robotic limbs now consumes cable in the process. Each length used repairs 3 burn damage, up to 15 damage per click.
-
Repairing brute damage to robotic limbs now uses 1 fuel per repair (click). Heal amount unchanged.
-
Self-repairing with cables or welders now incurs a 1 second delay between click and heal completion. Being repaired by a friend is still no delay (but requires a friend).
-
-
Fox McCloud updated:
-
-
Adds in the Kinetic Smasher as a mining purchase
-
Fixes slap emote text being the wrong partial color
-
Fixes the attack text of simple animals attacking human mobs
-
-
IcyV updated:
-
-
Adds in an amount of new graffiti
-
Fixes the issue of other graffiti only being able to be done in black.
-
-
Krausus updated:
-
-
Flavor text and records are no longer horrifically butchered when saved in the database.
-
-
TheDZD updated:
-
-
Lowered genetic instability damage thresholds by 5 across the board. Effectively meaning that you can have one additional minor power without shifting into the next threshold.
-
Lowered the rate at which damage scales with instability, and the decreased upper cap on each damage type.
-
The base activation probability for powers is now 100%, rather than 45%. Abilities affected include everything except Cloak of Darkness, Chameleon, No Breathing, Hulk, Telekinesis, and X-Ray Vision, which all have their own independent activation chances (varying from 5% to 10%).
-
Increases activation chances of TK (10% to 15%), No Breathing (10% to 25%), Cloak of Darkness (10% to 25%), Hulk (5% to 15%), X-Ray Vision (10% to 15%), and Chameleon (10% to 25%).
-
-
-
18 August 2016
-
Alexshreds updated:
-
-
pAIs can see the crew manifest again.
-
Engineers and Atmos Techs have access to the ORM
-
-
Ar3nn updated:
-
-
dusting playermobs now generates remains fitting for their race.
-
-
Chakishreds updated:
-
-
You can now click on objects in a gassy room at the expense of ninja floors.
-
-
Chopchop1614 updated:
-
-
fixes transformation sting not working.
-
transformation sting now checks if the target has DNA or not
-
-
Crazylemon updated:
-
-
Alt+Click should be quicker now
-
The Alt+Click panel vanishes only when you alt click a turf distant from yourself
-
Adds `json_to_object_arbitrary_vars`, a proc intended for use with SDQL
-
Eye color is tracked on the eyes only, instead of on the body.
-
The CMA panel no longer runtimes when you change species.
-
Deserializing a human now preserves hair and eyes.
-
Associative lists in VV now display properly again
-
Admins can now click on the DI panel buttons to debug the corresponding controller in VV
-
Fat people are now fat when naked.
-
Encased mobs can now examine
-
-
Crazylemon64 updated:
-
-
Makes teleportation checks more consistent, which will ensure that teleporting in the away mission no longer works.
-
People on the space ruins level no longer count as dead for assassinate objectives.
-
Space border turfs will now regain their destination when over-written and replaced on the edge of the map
-
The space manager will no longer runtime if a space ruin writes on the edge of the map
-
-
DaveTheHeadcrab updated:
-
-
ERT gloves reverted to how they used to be.
-
-
FalseIncarnate updated:
-
-
WOLOLO! Traitor Chaplains can now WOLOLO with the new Missionary Staff and Robes. WOLOLO!
-
-
Fethas updated:
-
-
The whitelist will respect addons better, didn't even have to make a ban appeal..
-
-
FlattestGuitar updated:
-
-
Detective's coolness variable cranked up to 14.5, they will no longer vomit over corpses.
-
Now you're less likely to vomit over a corpse if you're a normal human being.
-
golems now have their master saved in attack logs
-
-
Fox McCloud updated:
-
-
Adds in formal captain's uniform and armor
-
Adds rapier to captain's locker
-
Adds lace up shoes to captain's locker
-
Adds crown to captain's locker
-
Dramatically speeds up conveyor belts
-
Appendicitis and Disease Outbreak events will no longer impact clientless mobs
-
Fixes bandolier being invisible on spawn
-
Removes the jukebox from the bar
-
Detective Scanner, Fedora Tipping, Pontificating, and Cap Flipping are now action buttons
-
Cane Gun and NT Rep's cane now acts as actual canes
-
-
FreeStylaLT updated:
-
-
Fixed missing space transition tiles in emergency shuttle transit
-
Fixed lack of prisoner access to lower part of labor camp shuttle
-
Changed UO45's and MO19's away missions' external tiles to just airless ones.
-
Changed MO19's exterior to be more rock than ground, this is to make Linda cry less when this mission is passed.
-
-
General Chaos updated:
-
-
Ports TG's mech bay recharger code.
-
-
IcyV updated:
-
-
Adds an exploding chameleon flag for traitors.
-
-
KorPhaeron and Fox McCloud updated:
-
-
Merges Malf AI into traitor AI
-
Malf AI's starting CPU reduced from 100 to 50
-
Hacking APCs gives 10 additional CPU
-
Hacking APCs throws an alert to the AI when it's hacking that automatically clears when hacking is complete (sounds too)
-
Traitor AI's start off with a syndicate headset
-
Adds doomsday device module for AI's for 130 CPU; when activated, it will purge the station of all life if the AI is not destroyed after 7.5 minutes
-
Adds in AI upgrade modules which allows you to giving hacking abilities to the AI or allow it to have increase surveillance capabilities
-
-
Krausus updated:
-
-
Karma spending is now slightly more straightforward and sanity-checked.
-
Ghosts can now see non-crew antagonists in the Award Karma listing.
-
You can now ctrl+click on yourself to stop pulling something.
-
-
Kyep updated:
-
-
Added Syndicate Infiltration Teams (SITs), which are like Syndicate Strike Teams (SSTs) but focusing on stealth rather than direct combat. Useful for getting ghosts into rounds, spicing up rounds, having traitors with teamwork, and new kinds of traitor objectives like kidnap.
-
Fixed bug that Dust implants had no icon.
-
-
LittleBigKid2000 updated:
-
-
The arrivals checkpoint camera monitor is now connected to some camera networks by default.
-
Talking swords can now be understood by their wielders, and everyone else.
-
Engineering cyborgs now have floor painters. Absolutely nothing bad can happen because of this.
-
-
Norgad updated:
-
-
Coated Reinforced Walls now have unique sprites
-
-
TullyBurnalot updated:
-
-
Trash Bags fit in satchels/bags/duffelbags, but cannot be transported after being filled up.
-
Advanced Mops clean faster, can clean more
-
Holosign Projectors can create more signs
-
Ghosts can no longer create dirt
-
Dirt creation slowed down. "Clean Station" may actually be remotely possible now
-
Janitorial Closet tidied up
-
Can fill Light Replacers with boxes directly
-
Can recycle 3 broken/burnt bulbs into a functioning one
-
Can no longer cheat around NODROP by inserting NODROP lightbulbs into Light Replacers
-
Ghosts can no longer trip Proximity Sensors
-
Ghosts can no longer trip Infrared Sensors
-
Effects (like hallucinations) can no longer trip Proximity and Infrared Sensors
-
IDs are no longer dropped if their owner cryos with the ID inside a PDA inside a bag (very specific, yes)
-
-
Ty-Omaha updated:
-
-
Allows sechailer phrases to be selectable
-
Quick-equipping a PDA will now prioritize the PDA slot before the ID slot.
-
-
taukausanake updated:
-
-
Gives proper mix_messages for Uplink, Synthignon, and Synth 'n Soda drinks
-
-
tristan1333 updated:
-
-
Spacepod paint
-
-
-
08 August 2016
-
Ar3nn updated:
-
-
Telekinesis no longer is subject to meatspace problems
-
-
Chakirski updated:
-
-
Added animal AI holograms.
-
.45 Magazine sprites for the M1911 are now longer invisible.
-
Hoodies no longer look like labcoats while in hand.
-
Ectoplasm spawns in cult mining rooms instead of an invisible "weapon".
-
Duffel bag descriptions and names no longer contain "duffle".
-
Syndicate medical duffel bags can now be seen while in hand.
-
-
Crazylemon64 updated:
-
-
Adds a "Save" buildmode for admins to preserve their creations for later. This is currently in an early stage, so don't be surprised by errors!
-
-
FlattestGuitar updated:
-
-
Holy Water will no longer make you stutter for ages if you're not a cultist
-
-
Fox McCloud updated:
-
-
Fixes Orion Ship message being unheard when held in-hand
-
Adds headphones into the game as a loadout item
-
Removes fireproof core malf AI power
-
upgrade turrets malf AI power CPU reduced from 50 to to 30
-
Overload machine cost increased from 15 to 20
-
Override machine cost increased from 15 to 30
-
can override/overload field generators again
-
Machine uprisers will slowly die if they aren't attacking someone
-
Adds in Hostile lockdown malf AI power for 30 CPU
-
Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively
-
AI's no longer have flood mode on air alarms by default
-
Adds in lip reading malf AI power for 30 CPU
-
Allows accessories to hypothetically grant armor to their wearer
-
Greytide spear illusions actually have an attack sound now
-
fixes the wormhole event being much shorter than intended
-
-
FreeStylaLT updated:
-
-
Walls now melt when hot
-
Added actual coated rwalls - you can make them by clicking on an existing rwall with at least 2 plasteel in hand. Has infinite temp resistance.
-
Replaced all fake coated rwalls with new rwalls in both metastation (where they should be) and boxstation
-
Bandaging someone no longer stabs your eyes with bright green
-
Fixed repainted-to-wood metal flooring in courtroom - it's now actually wood
-
Fixed windoor in witness stand facing the wrong way
-
-
KasparoVy updated:
-
-
Traitors with the Maroon objective will no longer succeed if their target is in a locker on the shuttle.
-
Traitors with the Assassination objective will no longer fail if their target is assassinated/borged/debrained but on a Z-level greater than the derelict.
-
-
Krausus updated:
-
-
Fire will now totally consume you, rather than timidly hiding under your clothes.
-
Admin freeze overlays should no longer disappear from humans until they're actually unfrozen.
-
-
LittleBigKid2000 updated:
-
-
Adds cheap sunglasses. They provide no flash protection, but are available in the loadout and clothesmate.
-
-
Pinatacolada updated:
-
-
Makes the swedish gene spit out weird swedish chars and sounds
-
-
Ty-Omaha updated:
-
-
Fixes "is too cumbersome to carry in one hand" from showing up to other players.
-
-
Yurivw updated:
-
-
Condimaster now actually makes bottles. Removed: Unused options in admin secret menu are now removed.
-
-
chopchop1614 updated:
-
-
fix bluespace crystals exploit
-
-
-
03 August 2016
-
Fox McCloud updated:
-
-
Fixes a rare case where the singularity would escape containment when properly set up+contained
-
-
Krausus updated:
-
-
Non-respawnable ghosts will no longer qualify for mid-round rejoining (event antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this.
-
Cryodorms will no longer produce respawnable ghosts for the first 30 minutes of the round.
-
Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above their cryo pod, in the spooky cryodorms.
-
Cryodorms will now despawn you 90% faster if you willingly enter one.
-
Suiciding in the first 30 minutes of a round will no longer allow you to ghost and be respawnable.
-
Becoming a non-respawnable ghost lasts the entire round, even if you ghost in a respawnable manner later on.
-
You can no longer spam pinging posibrains, and cannot ping them at all if you cannot volunteer for one.
-
Missing limbs will now be grayed out on your health doll.
-
-
chopchop1614 updated:
-
-
Fixed the C4 labcoat exploding bug
-
-
-
01 August 2016
-
Crazylemon64 updated:
-
-
Admins are now able to print a map of the z levels.
-
Admins are now capable of scrambling the z levels' transitions.
-
Janiborg trash bags no longer fit down disposals when empty
-
-
Fethas updated:
-
-
(Maybe?)..We actually check if the race HAS BLOOD before trying to suck them
-
Due to various complaints from tajarans having hand cramps, glove makers have removed plasteel from the fabric.
-
Plasmaman can no longer be vampires.
-
Removes the mask check on both victim AND vampire, also makes the message a bit more obscure, so it's up to your imagination of where you are biting them and with what.
-
-
Fox McCloud updated:
-
-
Medical stacks now have 6 uses
-
Medical stacks now heal 25 burn/brute
-
Applying a medical stack to others is instant, no matter what
-
Applying any medical stack to yourself has a 2 second delay
-
Applying a splint to yourself has a 10 second delay
-
No more RNG fumbling of putting splints to yourself
-
Confirmation for applying medical stacks is now green
-
Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, 1 roll of gauze, and medipen.
-
Amount of splints in medical vendors increased from 2 to 4
-
Fixes weird icon updates when getting healed by medical kits
-
Adds in object burning system that allows things to be lit on fire
-
being on fire should heat you up a bit quicker and do a bit more damage
-
Novaflowers ignite you rather than uselessly heating you up
-
Adjusts a few pyrotechnic chems to better fit with other tweaks to fire damage
-
-
IcyV updated:
-
-
Adds a unique axe for Atmos-traitors
-
-
Krausus updated:
-
-
Probably fixed some very specific items messing up View Variables for no adequately explicable reason.
-
Fixed round-end antagonist report failing to print due to null objectives.
-
-
Kyep updated:
-
-
Added atmos grenade kit to traitor uplink.
-
Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes #5232
-
-
TheBeoni updated:
-
-
Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security one Added picture because i do not like that red label
-
-
TheDZD updated:
-
-
Shadowling ascendance and badmins pressing the "Destroy All Lights" button should no longer bring the server to its knees.
-
Broken lights will no longer re-break.
-
-
TullyBurnalot updated:
-
-
Using ATMs leaves fingerprints behind
-
-
Twinmold updated:
-
-
Nuke Ops airtank connected to pipenet now.
-
-
tigercat2000 updated:
-
-
Readded colored cable-cuffs.
-
Making stacks of metal rods now updates the icon correctly.
-
-
-
28 July 2016
-
A Giant-Ass Mountain of Salt updated:
-
-
Re-adds PDA slot.
-
-
Crazylemon64 updated:
-
-
Adds an explosion buildmode
-
"Drop Everything" in VV no longer causes limbs to fall to the ground.
-
-
FlattestGuitar updated:
-
-
IAAs can now select the classic secHUD in loadouts
-
adds bananas and suit jackets to the loadout system
-
adds dress shoes and fancy sandals to the loadout system
-
Miners can now get the mining coat from loadouts
-
-
Fox McCloud updated:
-
-
Fixes organ repair surgery saying an organ wasn't damaged when it actually was
-
Removes the 1 burn heal from regular ointment
-
Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)
-
Fixes a few crafting recipes not having the proper category
-
Fixes laser slugs not firing lasers
-
Adjusts the damage/consistency of improvised slugs
-
Adds in craftable bolas; throw them at someone to slow them down
-
Secvend starts off with e-bolas
-
Can make spears with personal crafting now
-
Fixes teacups and some other drinks having no sprite, in-hand, or object
-
adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies
-
Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand
-
Fixes cablecuffs not having a unique in-hand icon
-
Fixes cable coils not having a unique in-hand icon
-
All cablecuffs will be red, regardless of what they're produced from
-
Fixes an unlimited metal exploit
-
IV Drip sprites updated; has visual feedback for if it's injecting or taking blood
-
IV Drip injection rate dramatically increased
-
Warning ping for when someone is low on blood
-
Support for species with exotic blood type
-
Alt-Click to toggle between modes
-
Sensory restoration virology symptom no longer has anti-stun properties nor heals brain damage, but has a lower acquisition level
-
Damage convert heals individual limbs instead of healing overall damage (actual impact is low)
-
Librarian now starts off with a bookbag
-
Bookbag can now hold Bibles, cult tomes, books, and spellbooks
-
Can empty a bookbag into a bookshelf
-
Fixes an exploit where you could generate wood out of thin air
-
Fixes blobspores doing more damage than intended
-
-
Fox-McCloud updated:
-
-
Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws
-
Fixes some personal crafting behaving as other than intended
-
-
FreeStylaLT updated:
-
-
Fixed brig cell block APCs not getting power
-
Fixed space buggery Kyet made :angry:
-
Fixed missing light near labor shuttle dock
-
Fixed wrongly placed cobweb in solitary
-
Fixed basketball court not having a basketball
-
Added windows to brig processing entrance
-
Re-added the missing EOD and biohazard lockers in Armory
-
6 gas masks from Armory
-
Added grid check into random events.
-
-
Krausus updated:
-
-
The voting panel now uses the browser datum, which means it looks nicer.
-
The voting panel now updates while a vote is in progress.
-
When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in "vote".
-
Custom votes will now show full voting results upon completion.
-
Admins should no longer lose the "cancel vote" link in the voting panel.
-
View Variables should probably stop crashing admins.
-
The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen.
-
Admins now have click shortcuts for opening a player panel, showing mob info, and viewing variables. Specifics are in Hotkey Help.
-
-
Kyep updated:
-
-
Admins can now see attacks against SSD players more easily.
-
Clarified the text you get when examining a SSD player.
-
It is now possible for admins to remove a person's vamp thrall status.
Removes space parallax, due to server overhead, input lag & bugs
-
-
-
21 July 2016
-
Alffd updated:
-
-
Added a 6th Vulpkanin tail option.
-
Fixes animations, side view, and pixel fill for Vulpkanin tail 6
-
-
FalseIncarnate updated:
-
-
Engineers can properly show up for work with their hats and coats to keep warm.
-
-
Fox McCloud updated:
-
-
Tajarans and Unathi can now wear all shoe and glove types
-
Glove clipping removed except for black gloves, which makes them fingerless gloves
-
Adds sandals as a loadout option
-
Adds in simple animal mob spawners
-
Adds shielded hardsuit to the nuke ops uplink for 30 TC
-
Implements the powerfist and adds it to the uplink for 8 TC
-
Removed drinking glass shattering (regular bottle shattering is still a thing)
-
Captain's flask is now gold instead of silver
-
Bottles have a throwforce of 15
-
can crack eggs into drinking glasses
-
Detective's flask starts out with 30 units of whiskey
-
removes redundant object verbs that have an action button
-
Fixes up mindswap spell so it behaves more properly
-
Fixes genetic abilities action buttons not properly clearing
-
Fixes simple animals, silicons, and brains becoming perma deaf from flashbangs and other sources
-
ACTUALLY FIXES MINING APC
-
Fixes brig cell timers not having the option to flash people
-
-
FreeStylaLT updated:
-
-
Added new syndicate item Chameleon SecHUD to uplink store, available for all antags. It can morph into various eyewear while being a flashproof sechud.
-
-
Kyep updated:
-
-
Added new syndicate costumes to "select equipment" admin verb.
-
-
TullyBBurnalot updated:
-
-
More beds outside the Operating Theaters, Pajama Wardrobes outside and inside the Operating Theaters, an extra NanoMed Vendor, one Disposal Chute per OR, table with cards
-
Sinks moved closer to Surgical Tables, moved light fixtures in the Operating Theaters, tables with surgical tools now made of glass for maximum style points and Xenomorph Larva Whack-A-Mole
-
-
monster860 updated:
-
-
Brig timer UI reopening after being closed fixed.
-
-
-
20 July 2016
-
Allfd updated:
-
-
Added hologram fluff sprites
-
-
Ar3nn updated:
-
-
Gets rid of some weird lattices floating in mid-space
-
-
Chakirski updated:
-
-
Adds M.E. Reaper sprite.
-
AI can now choose a 32x64 reaper hologram.
-
Cigarette packs no longer show near-duplicate messages when examined.
-
-
CrAzYPiLoT updated:
-
-
Ports randomized space ruins from /tg/ station. There is a number of maps which can be spawned at any location on the empty z-level at roundstart, and up to three random ones will be chosen each round. Credits to KorPhaeron.
-
Lays the groundwork for a future lavaland implementation, if we choose to have it.
-
Adds a feature to the map loader where areas with the right var set can be distinctly initialized on map load - meaning separate APCs, and the like.
-
Using a z-level specific initialization freeze system, large elaborate maps like the cyberiad can be loaded without a single runtime, with minimal impact on the round elsewhere.
-
Adds a delete mode to the "Fill" buildmode - just alt-click for the second corner, and everything within will be removed.
-
Adds a "Jump To" function in VV, which is useful for getting an idea of what exactly you're looking at.
-
Added view count to newscaster feeds and messages.
-
-
Crazylemon64 updated:
-
-
Abductors consoles link correctly again
-
-
DaveTheHeadcrab updated:
-
-
Plastic explosives are now a subtype of grenades. Shouldn't be any noticable difference for players.
-
Plastic explosives no longer use the wire datum. You may directly attach an assembly holder (Such as a remote signaller + igniter assembly)
-
Adds X-4 shaped charges, designed for breaching explosively without harming the user. Pick some up at your local nukies r us.
-
Replaces tablecrafting with personal crafting, click the hammer icon by your intent selector to use it.
-
Removes the PDA slot, your PDA can now go in your ID slot (Again).
-
You can now alt click to remove an ID from a PDA, for quick interaction while it's in your ID slot.
-
Adds an overlay for an ID while it's inserted into your PDA.
-
-
FalseIncarnate updated:
-
-
Adds new Bottler machine for making unique beverages! Order one from cargo today!
-
Adds 6 new drinks obtainable via the Bottler. Get brewing!
-
Grapes now can be properly juiced again, as they now have the right kitchen tag.
-
Adds effects to the Paradise Pop reagents. Drink them all to unlock their powers!
-
-
Fox McCloud updated:
-
-
Adds in fans which can block atmospherics passing over them
-
All mass driver blast doors have a fan underneath them, allowing you to use them repeatedly instead of once
-
Fixes medical, security, and employment records not being displayed
-
Adds in a weather system
-
Removes most of the miner's uniform equipment from their lockers and puts it in a miner's wardrobe
-
Miners start off with a lot of their clothing equipment equipped to them
-
Miners now have unique headset sprites
-
Miners no longer have lanterns, but a seclite; they can attach this to their kinetic accelerators now
-
Miners have workboots instead of black shoes
-
Miners no longer have a default mining scanner but an advanced one that works at reduced range (5 instead of 7) and has a longer cooldown between pulses (5 instead of 3.5)
-
removed extra mining hardsuit from the outpost
-
removed medikit spam from outpost; now just a toxin kit and a regular medical kit
-
Bluespace crystals now earn you points and can be refined into bluespace polycrystal sheets
-
Spare vouchers from QM and HoP removed
-
removed armor from the fake tactical turtleneck
-
Can scan vending machines with your PDA to pay for items (if there's an ID in your PDA)
-
Sleepers no longer require a console to build, only the sleeper itself
-
Clicking on the sleeper brings up the menu that was previously brought up for the console
-
Adds in syndicate sleepers--these sleepers are not only syndie themed but also allow the user to inject chems into themselves while inside the sleepers
-
Sleepers can now inject silver sulfadiazine
-
removes cryofeeds from cryodorms and adds in 2 more cryopods
-
Fixes pre-spawned loaded belts not having proper overlays
-
nanites will no longer purge chems, but will now heal internal organ damage, attempt to mend fractures, and will no longer cure beneficial viruses
-
cold and hot drinks should now properly heat you up or cool you down (this also goes for medical reagents)
-
beer no longer reduces jitteriness
-
toxins special and antifreeze heat you up
-
banana juice and banana honk now heals monkeys
-
Fixes atrazine not killing nymphs
-
mining autoinjectors no longer poison you
-
combat hypospray now has omni+epinephrine+teporone
-
stimpack is now meth+coffee instead of meth+epinephrine
-
Cheese and synth meat amount creation scales with volume of the reaction
-
sprinkles now heals all members of sec (brig phys, sec pod pilot, magistrate, and IAA are no longer left out)
-
Fixes syndi+shielded+hos hardsuit sprite issues
-
Fixes wizard's who have a regular satchel set in their prefs winding up with none
-
Spellbooks are automatically bound to wizards at round start (no more ragin' exploitative mages)
-
Fixes mining outpost lacking an APC
-
Fixes being able to exploit and turn artificial bluespace crystals into regular bluespace crystals
-
-
FreeStylaLT updated:
-
-
Added courtroom, left of brig.
-
Remapped brig
-
Moved prisoner processing and evidence storage to the right of brig, next to Detective's office.
-
Changed current processing to Interrogation and a hallway.
-
Re-mapped Conference and Locker rooms.
-
Lots of other minor tweaks to brig.
-
Seriously, way too many small changes to list here, go and have a look at the brig yourself.
-
Removed temp. detainment and observation from brig.
-
-
KasparoVy updated:
-
-
Wearing a suit will no longer cause runtimes due to the way suit-collars are handled.
-
The north direction sprite of the Vulpkanin 'Patch' facial hair style won't hang a pixel off the head anymore.
-
-
Krausus updated:
-
-
All admins can now see "admin log" messages.
-
Admins can now toggle "admin log" messages on or off.
-
Admins will no longer be notified about ghosted admins jumping around.
-
Beating on simple animals will no longer be twice as noisy as intended.
-
Emergency Response Teams are now usable again.
-
-
Kyep updated:
-
-
adds botany, basketball court, individual cells, library computer and more to perma. Makes it far less boring.
-
Tracking implants are now useful, showing the implanted person's general location, and health status, on prisoner consoles.
-
The NODROP flag now works correctly on jumpsuits.
-
Improved admin 'select equipment' verb. ERT option now works, costumes get IDs and proper headsets, two new costumes added, and some outfits minorly tweaked (e.g: tunnel clowns get toolbelts).
-
Prevented NPCs being made into objective targets.
-
-
LittleBigKid2000 and TullyBBurnalot updated:
-
-
Stethoscopes can now be used to tell if a person's heart or lungs are damaged, or if they have any at all. Now they're actually useful instead of telling you the obvious in a vague way.
-
Stethoscopes can no longer be used to hear the heartbeat and breathing of a person that doesn't have a heart or lungs.
-
-
Tauka Usanake updated:
-
-
Adds a Hydroponics HUD and a night vision version of it that can both be created in R&D. It provides additional details on plants in hydro trays and soil plots. Shows the health, nutrient, water, toxin, pest, and weed level of the plant as well as whenever it is ready to be harvested or is dead.
-
-
TullyBBurnalot updated:
-
-
Handless cuffing no longer possible. Can still cuff people with one hand
-
-
TullyBurnalot updated:
-
-
Mobs with PSY_RESISTANCE are no longer valid targets for REMOTE_VIEW
-
When emagged, Photocopiers now have a cooldown if used to copy butts
-
-
Twinmold updated:
-
-
Fixes removing ID cards from laptops with the Eject ID verb.
-
-
monster860 updated:
-
-
A bunch of interfaces now use /datum/browser.
-
The ChemMaster now uses the asset cache, eliminating the enormous lag spike when you first use it. Yey!
-
Fixes the window not closing when selecting an icon for the chem-master
-
Fixes the chem master window not updating when selecting an icon
-
The chem-master icon selection window now has a 4x5 grid of icons.
-
-
tigercat2000 updated:
-
-
Gas tanks now have an action button for accessing their interface.
-
You can now shift-click on movable HUD elements (such as action buttons) to reset them to their initial position.
-
Implants with limited uses, such as freedom implants, now delete themselves when they run out of uses.
-
-
-
13 July 2016
-
Ar3nn updated:
-
-
Adds a silence button to newscasters, which will silence the regular update sounds
-
-
Chakirski updated:
-
-
Adds new bacon sprites.
-
Bacon can now be cooked from the grill. Just grill raw bacon.
-
Raw cutlets are now sliceable into raw bacon strips.
-
Plasma and N20 look more gassy.
-
-
DaveTheHeadcrab updated:
-
-
Greys no longer speak in wingdings.
-
Greys now have a species-specific language.
-
-
Fox McCloud updated:
-
-
Overall borg power useage has been lowered
-
Borgs who have completely run out of power can now still move around/see/talk, but they will be unable to interact with machinery/doors around them; they can still bump open doors, however. Borgs with no cell are still completely paralyzed and can't do anything.
-
IPCs are now properly impacted by space's burn damage
-
NT Rep's cane stuns for less and invokes a cooldown between use, similar to telebatons
-
Oxygen damage number changed a bit; damage is based upon volume lost more now
-
Species that have blood but are oxygen immune will now take tox damage
-
Health analyzers will now work with species with exotic blood and inform the user what type of exotic blood they have
-
Other machinery that display blood levels (op table, sleepers, advanced scanners, etc) will now work with exotic blood
-
Changeling regen will now properly restore blood if you have exotic blood fix Fixes being blurry for 20+ minutes when you were low on blood for a mere 3 minutes
-
Heart damage impacting blood volume removed
-
Nutrition draining when low on blood removed
-
Station cinematics shouldn't have inventory overlays over top of the animation
-
Station cinematics should properly clear off the screen and delete now
-
pAIs are no longer valid targets for gun turrets (like on the syndicate ship)
-
Adds in Rathen's secret, a new spell for the wizard that AoE stuns
-
Removed borg jetpacks
-
Adds in borg ion pulse system; borgs with ion pulse enabled consume extra power for each turf they move but can travel on space. Can upgrade any borg, at R&D with an ion pulse upgrade
-
Adds in cyborg self repair upgrade: very slowly repairs cyborgs at the cost of extra power. Available at R&D
-
Mining cyborg module tweaked slightly: GPS, shovel, mini welding tool and mini extinguisher added, wrench and screwdriver removed
-
reset borg module removes speed boost
-
Fixes borg's stun arm bypassing shields
-
-
KasparoVy updated:
-
-
Adds Vox compatible versions of all jumpskirts.
-
Adds Vox compatible version of the CMO jumpsuit.
-
-
Krausus updated:
-
-
Players will ALMOST DEFINITELY never get stuck as plants anymore. I mean it this time!
-
Fixed morgue trays not updating themselves when you ghost into/out of your body.
-
-
Kyep updated:
-
-
Changed access requirement on lethal injection locker to sec access (same access required for the chair its right next to.
-
Changed access requirement on exile implant locker to armory access.
-
Ghosts no longer miss out on ERTs due to not knowing it was called, or not being able to find the verb. They are now prompted about joining an ERT when one is called.
-
Fixed a condition where 'we are assembling an ERT' message is broadcast, but no ERT is generated.
-
Typo fixes in ERT messages.
-
Entering a cryo pod, then deliberately selecting OOC->Ghost, and clicking yes on the prompt, will now instantly send you to long-term storage, removing you from the round, despawning your body, freeing your job slot, and giving a new objective to any antag that had you as a target.
-
Announcements about someone entering long-term storage via a cryopod now include that person's rank.
-
When an antag target cryos, the message the antag gets about their objectives changing is now clearer.
-
-
TheDZD updated:
-
-
Adds "salts" as a say verb for deadchat ghosts.
-
-
TullyBurnalot updated:
-
-
Universal Recorder added to NT Rep Locker
-
Box of recorder tapes added to NT Rep and IAA Locker
-
Fax Guide added to Captain, HoS, HoP, NT Rep and IAA Lockers
-
Butt copy alert added to photocopiers
-
Butt copy alert comes with *ping noise
-
Photocopiers start with 60 toner
-
-
Twinmold updated:
-
-
Vampires with sleeping carp (traitor+vampire rounds) can now suck people's blood like normal.
-
-
monster860 updated:
-
-
The ChemMaster now uses NanoUI! Yey!
-
Alerts are no broken ghostly outlines
-
-
-
09 July 2016
-
Chakirski updated:
-
-
Adds disabled_component() to cyborgs.
-
EMPs now disable binary communication for as long as the stun time.
-
Syndicate thermal imaging glasses (mesons) can now be prescription upgraded like normal mesons.
-
Green glasses from the AutoDrobe can now be prescription upgraded.
-
-
FalseIncarnate updated:
-
-
Deepfryers are no longer arcane mysteries, and can be (de)constructed and upgraded.
-
-
Fox McCloud updated:
-
-
Grenade have a chance to explode when the person holding them is shot
-
Flamethrowers can release their tank's contents if the person holding them is shot
-
Can no longer self-trigger blocked shield events (ie: no self-harm to trigger a reactive teleport armor)
-
Hugging someone/shaking them up bypasses shield checks (oh no, hugs of death)
-
Riot shields have a +30% chance to block thrown projectiles
-
Hunter pounces are now a thrown attack as far as shield go, and yes, can be blocked by riot shields now
-
Energy shields no longer block anything other than beam and energy projectiles
-
Being able to be pushed is based on the block chance of the item you're holding instead of it just being based on riot shields
-
Adds in cursed wizard heart, purchase it from the wizard's spell book for 1 point, but be wary of not keeping the heart beating...
-
-
FreeStylaLT updated:
-
-
Added a bunch of new items to maint, some rare uplink gear included. (see PR for full list)
-
made gas masks, nothing and extinguishers less common in maint
-
-
Krausus updated:
-
-
Players probably won't get stuck as plants forever anymore. Probably.
-
Refactored job ban checking, which should massively reduce round start-up time.
-
Job bans/unbans will now take effect instantly, rather than at the next server restart.
-
-
TheDZD updated:
-
-
DNA injectors no longer always activate powers that are supposed to have a chance to activate.
-
Dionae can no longer activate the radiation disability, nor the run superpower except via adminbus.
-
Adds genetic instability, which causes a variety of negative effects, including toxin damage, burn damage, cloneloss, and even gibbing. Effects get worse as stability gets lower, burn damage starts below 85 stability, tox and clone below 70, and gibbing once you're below 40.
-
Adds Curse of the Cluwne touch attack spell, which wizards can pick, heavily based off of the same spell from Goonstation. Said spell adds an unremovable honk tumor to the target, gives them NODROP neon green clown gear, makes them stutter, makes them almost eternally fat, confuses them, makes them clumsy and speak in Comic Sans, and severely brain damages them. Use it on a cluwne however...
-
Fixes a bug where honk tumors would cause NODROP items to still be moved, despite being unable to be unequipped.
-
-
TullyBurnalot updated:
-
-
Botanist access to the morgue revoked
-
Added custom messages for evil faxes
-
Added unique text body for each non-evil fax template
-
Added a "Keep up the good work" fax template
-
Added a "ERT Instructions" fax template
-
Photocopiers can be emagged
-
Emagged photocopiers deal 30 burn damage to all mobs copying their butts
-
Deconstructing Comfy Chairs yields 2 metal sheets
-
Boxes no longer allowed inside evidence bags to prevent them going into themselves
-
Monocles are now prescription upgradable
-
Monocles added to Loadout selection
-
Spinning a revolver's chamber makes a noise again
-
Revenants can actually be killed now.
-
AntagHUD activation disqualifies player from rebooted drones
-
Sergeant Ian hat now visible
-
-
Twinmold updated:
-
-
Fixes the inconsistency of getting 2 metal rods when you wirecutter a destroyed grille down to 1.
-
-
-
07 July 2016
-
Ar3nn updated:
-
-
Adds tech levels to RnD console main menu
-
-
FalseIncarnate updated:
-
-
Chicks no longer lose their souls (literally) when becoming adults.
-
Intercoms, fire alarms, and air alarms no longer contain internal portals to a realm of infinite cables and circuit boards.
-
-
Fox McCloud updated:
-
-
Space lube damage removed and duration reduced from 7 to 5
-
Azide and CLF3+Firefighting foam now play a bang sound when mixed
-
Can now pet pAI's with help intent
-
Fixes sechuds and nightvision sechuds having flash protection
-
-
FreeStylaLT updated:
-
-
Added windows and a missing firelock to Genetics/Cloning
-
Tweaked layout of Genetics slightly
-
Added photocopier to R&D.
-
Tweaked RD's office layout slightly
-
Changed access on Tcomms' external airlocks' buttons to be same as general Tcomms access
-
fixed the airless tiles in Assembly Line's windows
-
-
KasparoVy updated:
-
-
Adds improved Vox mask/goggle sprites.
-
Adds Vox-compatible versions of most suits.
-
Adds species-fitting and icon override handling to clothing accessories and suit collars.
-
You can now open/close Clown Officer and Soldier coats.
-
Adds by-species tail hiding.
-
Tidies up and refactors the way the Captain's space helmet shows Vox hair but hides every other species'.
-
Reactive armour's sprite will now update as soon as you turn it on/off or EMP it.
-
-
Krausus updated:
-
-
Fixed borers dying in hosts who happened to be somewhere cold, such as space. Even if their host was in a space suit.
-
Fixed borers forgetting to detach from a host when it died.
-
Fixed borers being able to assume control of a dead host.
-
Fixed dead borers in a host being able to speak with the host and ghosts.
-
Fixed employees starting every shift at least 3 minutes late. You aren't getting paid to stand around, people!
-
Fixed animal beatdowns being twice as noisy as they should be.
-
Pod lock busters should now properly bust pod locks.
-
The late-stage effects of the "sensory destruction" disease symptom should now properly destroy your senses.
-
Autotraitor should now continue picking new in-game traitors, instead of picking one and dying.
-
Lacking a head no longer makes you immune to becoming a husk or skeleton.
-
Security and medical records should probably stop crashing people.
-
Altering details on an Agent ID Card will now actually update what's seen when examining the card.
-
-
Kyep updated:
-
-
Fixes NT Special Ops Officer's headset so he can correctly hear, and talk on, the Special Ops (deathsquad) channel.
-
Fixed oversight in keycard authentication devices that incorrectly treated trialmins like fullmins, resulting in situations where calling an ERT became impossible.
-
If an ERT request gets no answer for 5 minutes, admins now get a one time reminder that it was sent.
-
-
TheDZD updated:
-
-
Burst fire selection is now a proc, as it was meant to be, rather than a verb.
-
-
TullyBurnalot updated:
-
-
AI can no longer interact with IV Drips
-
Robots can no longer remove beakers/blood bags from IV Drips
-
Fixed clown door deconstruction
-
Fixed mime door deconstruction
-
-
-
02 July 2016
-
Fethas updated:
-
-
adds comfirmation dialogs to transforms from player panel
-
-
Fox McCloud updated:
-
-
Adds in laughter demons
-
Can summon laughter demons as a wizard
-
Chem master can produce instantaneous medical patches if all chems are safe
-
Can now purchase sniper rifle and associated ammo on uplink during nuke ops
-
Most melee and laser armor values halved or reduced; some bullet armor reduced slightly
-
Slowdown on most armor and spacesuits reduced by 1 (chaplain armor is still slow though)
-
Mining armor caps out at 60 melee resist as opposed to 80
-
Ling melee armor reduced; bullet and laser values buffed a bit and slowdown removed
-
Chameleon jumpsuit has a little bit of armor
-
Detective's forensic jacket now has identical armor to the native detective jacket
-
Armor penetration added to energy swords, chainsaws, scythes, and spears
-
Fixes stun batons, telebatons, and abductor batons piercing/bypassing shields
-
-
FreeStylaLT updated:
-
-
Adds appropriate battle yells to sleeping carp
-
-
KasparoVy updated:
-
-
Engineer boots that've had their toes cut open now have a sprite.
-
Vox now have engineer workboot sprites.
-
Removes unused SWAT boot sprites that were really just copypasted jackboot sprites.
-
-
Krausus updated:
-
-
The late-join job listing is now big enough to show all the jobs at once, and organizes them into labeled categories.
-
Fixed Hotkey Help and hotkey mode toggle messages not appearing.
-
The late-join job listing will now ignore (mis)clicks for the first second after popping up.
-
-
Kyep updated:
-
-
"Loyalty" implants are now known as "Mindshield" implants
-
Admins playing CC jobs can no longer get antag status from autotraitor.
-
-
Tastyfish updated:
-
-
There's essentially a completely new space hotel map! Explorers rejoice!
-
-
TheDZD updated:
-
-
Chance for vampires to burn in the chapel has been greatly reduced (from a 35% chance down to 8% per tick).
-
Vampires do not scream from chapel/space burning until they actually start catching fire.
-
Threshold for vampires to catch fire from space/chapel burning changed from 60 health to 50 health.
-
Fire stacks from vampire burning no longer apply twice 35% of the time while below the health threshold.
-
-
VampyrBytes updated:
-
-
No more *me emoting from your corpse!
-
-
monster860 updated:
-
-
Fixes ghosts having a generic icon when darkness is toggled off
-
-
tigercat2000 updated:
-
-
There's a new tab in the character setup screen, "loadouts". This allows you to spawn with a limited number of preset items.
-
Character setup now uses #defines for the different tabs.
-
-
-
28 June 2016
-
CrAzYPiLoT updated:
-
-
Replaced the current recycler sound with a new one.
-
-
DaveTheHeadcrab updated:
-
-
Adds workboots to be worn by engineers.
-
Fixes the scanner's search functionality.
-
-
FalseIncarnate updated:
-
-
To save on adhesive costs, Nanotrasen has stopped gluing stools to the floor. The resulting bodily injuries probably won't cost more than the glue.
-
-
Fethas updated:
-
-
you can now pick up potted plants and stealth
-
-
FlattestGuitar updated:
-
-
changes some alcohol values, the weaker ones are no longer as weak
-
refactored alcohol, you can now take short breaks between sips and still pass out in a gentlemanly manner
-
different species have different levels of alcohol resistance, check in with your bartender for more information
-
The medical HUD will now be a bit smoother. Neat.
-
-
Fox McCloud updated:
-
-
Warden starts off with a pair of Krav Maga Gloves
-
New Steal objective: steal the warden's krav maga gloves
-
Clonepods will automatically suck in nearby meat
-
Slime processors will automatically suck in nearby dead slimes
-
Actually fixes vamp chaplains
-
Fixes clumsy check on guns not working properly, resulting in people with glasses shooting themselves in the foot
-
pAI candidates can now see who requested them
-
-
KasparoVy updated:
-
-
Adds Yi to Vox-pidgin syllables. (Port from VG.)
-
Adds framework for icon-based skin tones. (Port from VG.)
-
Adds Vox-compatibility for all remaining eyewear.
-
Raiders now get a random skin tone and eye colour on spawn.
-
Species default hair, facial hair and head-accessory colours can now be defined.
-
Newly created Vox mobs will spawn with the same hair colour as they used to have pre-greyscaling.
-
Noir vision will no longer grey out the HUD. (Port from VG.)
-
Tails will not be coloured if the person's species doesn't have skin colour.
-
Vox hair (head and facial) have been greyscaled and can now be customized by the full colour range.
-
IPC parts from the mech fabricator won't turn IPCs invisible upon attachment anymore.
-
-
Krausus updated:
-
-
Added a custom runtime error handler.
-
Added an in-game runtime viewer.
-
-
Kyep updated:
-
-
Admins now hear boink sound when faxed, command sends ERT request, etc
-
Admins can reply to faxes via radio
-
Admins can reply to faxes with pre-written fax templates
-
Admins can reply to faxes with 'evil faxes', special faxes that have negative effects on their intended recipient (and nobody else)
-
Admins can now join as "Nanotrasen Navy Officer", and "Special Operations Officer". They spawn on adminstation and ERT office, respectively. They are not announced and do not appear on crew manifest.
-
"Select equipment" verb outfits tweaked for consistency with the above job outfits
-
Teleporter on admin station now works.
-
Added antag-only warning to bee briefcase, to reduce chances of traitors killing themselves with it.
-
-
LittleBigKid2000 updated:
-
-
Space explorer corgis can now safely explore space
-
-
Norgad updated:
-
-
Maintenance around the incinerator has been expanded.
-
Engineering maintenance finally has an APC.
-
The incinerator has been moved eastward, there is now a construction area in it's previous location.
-
-
Tastyfish updated:
-
-
Cryo tubes, sleepers, and body scanners now eject random items the occupant dropped, upon the occupant being ejected.
-
-
TheDZD updated:
-
-
Adds an adminbuse gun that fires gun mimics, you can varedit the gun's `mimic_type` var to any gun path, and it'll fire that gun as mimics. By default it fires stetchkin pistol mimics.
-
Fixes minor issues caused by some guns having text paths for power cells.
-
Fixes some runtimes and inconsistencies with the telegun and temperature gun.
-
The Tesla engine has acquired a grudge for lockers, and will now smite any in its path.
-
Unstable bluespace teleportation devices have been removed from energy guns, meaning they should no longer teleport from one hand to another when switching firing modes.
-
-
Twinmold updated:
-
-
You can once again resist borer control with the Resist verb.
-
-
VampyrBytes updated:
-
-
Emotes can now be accessed through verbs as well as say *
-
Emotes accessed through say * no longer take parameters after a -
-
Emotes now take parameters through input boxes
-
Emotes now have support for blind and deaf characters
-
Emotes now personalise messages
-
Flip can now be targeted with or without a grab
-
All emotes that are affected by being muzzled now make the user make some kind of noise
-
monkeys now have access to all the emotes that the npc tries to perform
-
Leap genetics ability lets you jump over things
-
-
monster860 updated:
-
-
UI now gets it's own plane
-
RnD console now uses NanoUI! Sweet!
-
Fixes tranquillite being outside the box in the materials list. Mimes are supposed to be trapped inside a box, not outside one.
-
Replaces the weird unicode "x" character in some design names with the actual letter "x" so that it doesn't fuck up NanoUI
-
RCD gets a UI
-
RCD-built airlocks can now receive different types and accesses.
-
You can now shift-click to examine as silicon, instead of ctrl-shift-clicking, which is something absolutely no one would guess.
-
Pulsing multiple doors' "open door" wires at the same time using a remote signaller now actually opens them at the same time.
-
Fixes wormhole projector not having an icon.
-
Wormhole projector has 0 failchance now.
-
Portals made by wormhole projectors can be removed via a multitool
-
Fixes ghost being able to request docking at trader ship consoles
-
-
tigercat2000 updated:
-
-
Ported goon HTML chat from /vg/ / Goon
-
All uses of \black have been removed
-
All uses of \icon have been replaced with bicon()
-
-
tkdrg updated:
-
-
Admins now have a verb to wipe all scripts from telecomms.
-
-
-
19 June 2016
-
DaveTheHeadcrab updated:
-
-
Defibs now must be used within 3 minutes of death.
-
Combat defibs now induce heart attack when you stun with them (Emagged defibs have a 10^ chance to do this)
-
-
Fox McCloud updated:
-
-
Adds in the ability to make latex glove balloons (cable coil+latex glove)
-
Fixes latex gloves not having an in-hand icon for the left hand
-
Telephones will now ring when activated in-hand
-
Force on telephones removed
-
The break room privacy shutters now apply to all windows in the medical break room and not just the ones out front
-
His Grace grants massive stamina regeneration
-
pre-made styptic, silver sulfadiazine, and synth flesh patches now apply instantly
-
Styptic and Burn patches now have unique icons
-
Partially fixes graffiti so it's actually visible
-
-
FreeStylaLT updated:
-
-
changed its to it's in lockbox description
-
changed \red to formatting
-
changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to 1 TC
-
-
KasparoVy updated:
-
-
Secure briefcase now has the same flags, hitsounds, attack verbs, throw speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins now.
-
Dethralling a Shadowling thrall that has darksight activated clears their darksight.
-
-
LittleBigKid2000 updated:
-
-
The vox raider's base is now filled with nitrogen instead of regular dusty air.
-
-
TheDZD updated:
-
-
Teaches camera assemblies the meaning of the word "respect" (for NODROP items).
-
Sates the insatiable hunger that orange shoes once had for secborg cuffs.
-
Cryodorms will no longer kick you to lobby if you have logged off when they despawn your body, they will now always ghost you.
-
The defense values on the riot armor helmet is now identical to those on the riot armor suit.
-
Knight armor (including the chaplain's crusader armor) now has a slowdown of 1 instead of no slowdown.
-
-
Twinmold updated:
-
-
Fixes being able to eat cybernetic implants so you cannot eat them/force feed them to people.
-
Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability to insta-kill IPCs/incapacitate those with mechanical hearts.
-
Lowers amount of confusion given from Revenants from 50 to 20 per Defile.
-
Sets a maximum confused amount from the Revenant's Defile ability (now 30).
-
Makes Syndicate Bombs show a more accurate time remaining until detonation.
-
-
monster860 updated:
-
-
Makes stock parts build 5x faster
-
Adds a last-second loop-back sort pipe so that items with a mail tag don't end up on the disposals conveyer, and get flushed right back around. This enables an item to be sent from anywhere on the station to anywhere else on the station without going through the disposals conveyer.
-
Fixes a bug where drones can get stuck if they have their destination set to the RD office. This also fixes the bug where attempting to send a package from the test lab always ends up in the RD office.
-
-
tkdrg, Delimusca, Aranclanos, TheDZD updated:
-
-
Gun mimics (including wand, staff, projectile guns, and energy guns) created by the staff of animation will shoot things.
-
Mimics created by the staff of animation now have googly eyes.
-
Fixes the disturbing lack of death caused by wand of death projectiles.
-
-
-
12 June 2016
-
CrAzYPiLoT updated:
-
-
Fixed the long-lasting bug of handcuffed people keeping their chainsaws.
-
-
Crazylemon64 updated:
-
-
No more language message-spam on roundstart
-
-
DaveTheHeadcrab updated:
-
-
Adds a new icon for the detective's scanner.
-
Detectives scanner now has access to DNA and fingerprint records.
-
-
Fox McCloud updated:
-
-
Adds three new chaplain weapons: pirate saber, multiverse sword, and possessed/talking sword
-
Fixes not being able to sheath the claymore in the Crusader Armor
-
Adds in a mocha drink
-
Fixes ice being unobtainable for the jobs that use it most
-
Fixes laser armor losing its reflecting ability
-
Fixes the lack of progress bars for more stack-based construction
-
Fixes Experimentor producing coffee machines instead of cups
-
Can deconvert mindslaves by removing their mindslave implant
-
Can deconvert Vampire thralls by feeding them holy water
-
Fixes mindslaves not having a HUD for the master and mindslave
-
Fixes being able to duplicate just about anything in the Experimentor
-
Fixes not being able to use tank transfer valves or one tank bombs in the Experimentor.
-
Fixes infinite-throw spam
-
Fixes being able to resist out of grabs by moving (that is to say, it'll actually work now)
-
Fixes passive grabs using the wrong HUD icon
-
Tabling duration reduced from 5 to 2
-
Can no longer wield double-bladed energy swords as a hulk
-
Fixes on map stools having the wrong offsets, making it look like you're not sitting on them
-
-
FreeStylaLT updated:
-
-
Added (Enabled) Mind Batterer for Traitors
-
Fixed uplink implant description (Said 5 when actually gave you 10 TCs)
-
-
Glorken updated:
-
-
Shifts Zeng-Hu left leg over in order to regain thigh gap.
-
Chops off a pixel on Bishop feet so that they fit into shoes.
-
-
KasparoVy updated:
-
-
Old placeholder IPC butt sprite replaced with the finished QR-code sprite.
-
-
Krausus updated:
-
-
Fixes ghosts failing to follow mobs that move in unusual ways
-
Fixed tape allowing mobs with sufficient access to move through solid objects.
-
-
Many -tg-station Coders, TheDZD updated:
-
-
Old gun code is now gone.
-
Ports the vast majority of TG's gun code and their guns (any previously unavailable guns, and newly-added guns will remain unavailable to players). Expect some changes that might not be listed here due to the sheer scope of this refactor.
-
Probably some new bugs.
-
A lot of old gun bugs.
-
Mouth suiciding with a gun no longer instantly kills you, you fire the gun at yourself at 5x damage (assuming it even did damage to begin with).
-
Mouth suicide shooting does not work on harm intent.
-
You can now bash people with guns while on harm intent instead of shooting them point-blank.
-
You can now mouth suicide other people, doing so still takes the full 12 seconds to mouth suicide, but has the same 5x damage multiplier.
-
Vox spike throwers are real guns that fire spike bullets now, instead of just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor piercing, cause a 1 second stun (not the kind that drops you to the floor), and cause some bleeding. They have 2 round burst fire as well, and have 10 shots per clip. A new should should recharge every 20 or so seconds.
-
Xray lasers now have a maximum range of 15 tiles.
-
Zoomed guns now actually fire accurately while zoomed.
-
Using Suicide with guns now actually does gun-like things.
-
The clown no longer deletes guns if he fucks up with them due to being clumsy.
-
Emitters no longer become inaccurate over long ranges.
-
Power gloves now override middle-click and alt-click when worn.
-
Power gloves give a notification when worn.
-
Power gloves now have special examine text when examined by an antagonist.
-
Proto SMGs now only have a 21 shot clip.
-
-
Spacemanspark updated:
-
-
Adds the ability to make a more irritated buzz noise at people as a synthetic. The original buzz is still there.
-
-
Tauka Usanake updated:
-
-
Adds more belt icon overlays
-
-
Twinmold updated:
-
-
Nar'Sie AI Hologram and Error Sprite
-
Fixes space pod equipment variable. Can now properly install/uninstall equipment.
-
Check Seat verb no longer pulls out installed equipment.
-
You can now have a passenger in your pod if you have a passenger seat.
-
-
monster860 updated:
-
-
Adds comical implant. It is an implant that causes you to have a comic sans voice. It can be made in the protolathe using bananium.
-
The comical implant now spawns by default inside IPC clowns
-
Fixes the window getting stuck when you try to drag or resize a NanoUI window too fast with Fancy NanoUI enabled
-
Fixes a small quirk with the resize handle.
-
Fix javascript error in cargo UI
-
-
pinatacolada updated:
-
-
removes atmos tech SOP from supply SOP
-
Fixes defibing people without a heart
-
Fixes defib saying it didn't work stopping a heart attack when they do
-
-
-
02 June 2016
-
CrAzYPiLoT updated:
-
-
Fixed a text problem in virtual gameboard description.
-
Made gameboards deconstructable and movable.
-
Added a light to gameboards. Pretty!
-
-
Crazylemon64 updated:
-
-
There will no longer be a mountain of startup runtimes when people have custom languages.
-
-
DaveTheHeadcrab updated:
-
-
Removes xenobio golem rune creation sound
-
Added overlays for sec belts that reflect the items stored therein.
-
-
Fox McCloud updated:
-
-
Fixes Chapel and Chaplain's office not having a light switch
-
Fixes mass driver only being usable once due to weird pressure
-
Fixes chapel being overly dark near coffins
-
Fixes not being able to sheath the claymore in the Crusader Armor
-
-
IK3I updated:
-
-
crate cargo system
-
passenger seat system
-
loot box secondary cargo system (install it and your pod has a standard inventory)
-
lock busters for the CE and Armory
-
incappacitated people can't operate the door controls anymore
-
Items dropped in a pod can now be scrounged up
-
security can rip you out of an unlocked pod
-
The pod code isn't full of tumors any more
-
-
Tastyfish updated:
-
-
Holsters now have an action button while on your suit again.
Allows Chaplain to select a wide new range of null rod customizations
-
Slightly increases null rod damage (15->18)
-
Fixes abductors speaking other languages
-
Fixes traitors getting less TC on some game modes
-
-
QuinnAggeler updated:
-
-
All lazarus revived mobs become valid for pet collaring
-
-
Tastyfish updated:
-
-
Adds a suicide for light tubes.
-
Progress bars, buttons, and several of the values in UI's are now animated.
-
Deconstructing glass tables now gives a stack of 2 sheets of glass.
-
-
monster860 updated:
-
-
Upgrading the experimentor will no longer reduce the chance of upgrading an item's tech
-
Guest passes can now be attached to an ID card.
-
Adds a HoP guest pass computer, which is like a normal guest pass computer, but using an ID with ID computer access will allow it to issue guest passes with any access.
-
Adds the HoP guest pass computer to the HoP office.
-
Moves the guest pass computer in robotics to RnD.
-
-
-
25 May 2016
-
CrAzYPiLoT updated:
-
-
Adds an unread change notification.
-
-
Fox McCloud updated:
-
-
Removes Dragon's Breath Recipe
-
Removes Ghost Chilli Juice
-
Fixes buckled flipping over someone
-
-
IK3I updated:
-
-
Sleepers, scanners, and borg chargers no longer remove you from existence when destroyed
-
Hostile mobs are no longer fooled by your clever scanner and recharger tricks
-
-
-
24 May 2016
-
CrAzYPiLoT updated:
-
-
Adds the ability to attach signalers to bear traps. Stealthy hunting!
-
-
Crazylemon64 updated:
-
-
You can now fasten the circulators in the TEG kit with a wrench - no adminbus needed to set it up, now
-
You can now rename cassette tapes with a pen.
-
You can now wipe data from a tape from its right-click menu.
-
-
FalseIncarnate updated:
-
-
Adds 4 new types of fudge for the chef to make: Peanut, Chocolate Cherry, Cookies 'n' Cream, and Turtle Fudge.
-
Normal fudge recipe now uses milk instead of cream.
-
Mutant/Modified/Enhanced plants will no longer infinitely increase their name length, and instead will be simply "mutant", "modified", or "enhanced" plant as determined by the last type of modification they were subject to.
-
Bees can no longer phase through hydroponics lids, giving botanists a way to finally stem the tide of pollination.
-
Premade beeboxes now spawn with the right type of bees, specifically of the worker caste.
-
-
Fox McCloud updated:
-
-
Donk pockets have more omnizine, but only upon fully consuming the donk pocket
-
swarmers will drop an artificial bluespace crystal on death
-
Orion Trail guards now drop an energy shield and C20R on death
-
Reviving simple animals with strange reagent will prevent them from dropping any further loot
-
-
KasparoVy updated:
-
-
Rejuvenating a mob now unbuckles them correctly (if they're buckled to something).
-
Rejuvenating a mob will no longer remove their hair.
-
Rejuvenating a mob will no longer permanently blacken their eyes.
-
Rejuvenating a mob will no longer remove their prostheses with fleshy limbs, it will just fix the prostheses.
-
Rejuvenating a mob will not remove organs/limbs belonging to other species if said organs/limbs are in the same place(s) as the mob's default organs/limbs would be.
-
Fixes a runtime when trying to flip with an object other than a grab in your hand.
-
Doing a 'cybernetic repair' procedure on the head of a disfigured IPC will re-figure them.
-
Rejuvenating a mob will only regrow organs/limbs that are missing (by comparison to the standard organs for their species).
-
The regenerate_icons proc will now update skin tone and body accessories properly.
-
Organ rejuvenation now clears disfigurement and closes open wounds.
-
Rejuvenating a mob will end all in-progress surgeries.
-
Vox get their cortical stacks back, since the non-implant ones don't interfere with the Heist game-mode.
-
Rejuvenating a long-dead or husked mob will now clear the appropriate mutations.
-
-
QuinnAggeler updated:
-
-
Species disguise variable for clothing items
-
Species disguise string, "High-tech robot," for cardborg suit and helmet
-
ABSTRACT flagged clothing items will not be displayed on examination
Cryopods will now always display the occupant's name
-
-
KasparoVy updated:
-
-
Fixes a runtime with Dioneae by repathing their limbs.
-
-
QuinnAggeler updated:
-
-
Makes dehydrated space carp description more accurate and informative
-
-
monster860 updated:
-
-
Adds the permanent teleporter. Use the circuitboard on a teleporter hub to set the target before constructing it.
-
-
-
17 May 2016
-
AugRob updated:
-
-
Add screwdriver sound when opening/closing panels on airlocks
-
-
Fox MCCloud updated:
-
-
Removes "harm" traitor objective
-
Increases non-escape/hijack/die objectives from 1 to 2
-
Tweaks available objectives to traitors a bit
-
-
Fox McCloud updated:
-
-
Players can no longer see how many players have readied up or who has readied up
-
Hulks, Shadowlings, and Golems can no longer use laserpointers
-
Adds in the ability to flip over someone with *flip
-
Fixes and improves foam to better interact with reagents
-
-
KasparoVy updated:
-
-
Refactors hair so it's on the head (organ).
-
Adjusts some Vox hair style names so they're consistent with all others.
-
Refactors Morph and the order by which options are presented.
-
Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
-
Fixes some typos.
-
Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
-
Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
-
Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
-
Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
-
Adds a new Vox hairstyle.
-
You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
-
-
monster860 updated:
-
-
Fixes sleep() in telecomms
-
Windows can now be constructed and deconstructed using RCD's.
-
-
-
10 May 2016
-
Crazylemon64 updated:
-
-
Ragin' Mage creation works correctly again.
-
-
FalseIncarnate updated:
-
-
Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC)
-
Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees still murder them though)
-
-
FlattestGuitar updated:
-
-
Robots now slur and stutter robotically
-
Adds tape gags. Click on someone with a roll of tape to shut them up!
-
-
Fox McCloud updated:
-
-
Removes material efficiency upgrades from the mech fab and protolathe
-
Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down from 1 up to 4)
-
Fixes materials exploit duplication
-
Fixes the protolathe locking up under some circumstances
-
Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced.
-
removes fungus from mushrooms
-
adds fungus to "mold" plant
-
adds mold seeds to hydro vendor
-
bumps up ???? reagent from 1 to 5 on bad recipes
-
Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS
-
Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison bottles
-
Initropidril now has a recipe
-
Adds a number of new reagents
-
Brain burgers now contain prions instead of mannitol
-
Scientists and chemists can no longer purchase traitor poison bottles
-
random drug bottles now have a much wider range of reagents in them
-
Fixes UI On slot machine saying it costs 5 credits when it's 10
-
Fixes abductors having tails
-
Fixes traitor scissors having a different hair-cutting sound
-
Fixes simple animals not dying right away when they reach zero health
-
Fixes a few farm animals, simple xenos, and a hivebot from having incorrect health
-
Buffed health pack usage on simple animals (should heal roughly 20 damage on them, per use)
-
Emotes no longer need to be purely lowercase to work
-
Chaplain can now select a green book as his Bible
-
Adds in His Grace, a hijack-only traitor item for the Chaplain
-
-
IK3I updated:
-
-
Added key and tumbler based pod locks
-
Made Pod Locks and keys buildable in Pod Fabricator
-
Made Pod Keys recoverable from cryo
-
Added lock to Security Pod
-
Added a key for Security Pod to HoS and Pod Pilot Offices
-
New sprites for several pieces of pod equipment
-
Using a multitool on a decalock now gives usable info
-
-
NTSAM updated:
-
-
Fixes the stuttery rainbow screen for IPCs.
-
Fixes the green IPC screen.
-
-
QuinnAggeler updated:
-
-
Adds a sound emote for the Drask
-
Gives Drask the ability to eat soap
-
Adds a racial flag for the Drask
-
Makes syndicate, paramedic, clown, and EVA helmets display correctly on Drask
-
-
tigercat2000 updated:
-
-
The station blueprints can now show you where wires/pipes/disposal pipes are supposed to go.
-
-
-
04 May 2016
-
CrAzYPiLoT updated:
-
-
Adds gameboards to bar and permabrig.
-
-
Crazylemon64 updated:
-
-
AIs are no longer created for temporary messages.
-
-
Fethas updated:
-
-
Sniper Rifles for nuke ops.
-
you can now actually shove heads on spears again.
-
Before i removed the traitor chemist item i cleaned up the harm reaction code paths.
-
-
FlattestGuitar updated:
-
-
cheap lighters only damage your hand if you fail to properly use such a complicated contraption, not the whole body
-
ports /tg/ Foam Force guns, now you can shoot foam at your enemies /with style/
-
-
Fox McCloud updated:
-
-
Slime batteries now self-recharge.
-
Adds in door wands--control doors from range
-
Each head of staff (and the QM) starts off with a door wand to control the doors in their respective departments
-
Fixes nutrition alert icon kicking in too early
-
Adds in a new hairstyle
-
Fixes cig icons not updating under some circumstances
-
Updates the Tesla; it will now have to be "fed" or it can run out of energy; the rate at which it gains additional energy balls and power has been greatly lowered.
-
energy ball will now be drawn towards the singularity beacon
-
fuel tank explosions a bit stronger and will arc tesla blasts further
-
Tweaked some game mode population requirements to enhance general game mode balance and player experience.
-
Reworks overdosing to have more unique effects and also scale, in part, on volume
-
Epinephrine, Atropine, and Ephedrine have a lower OD threshold
-
Saline penetrates the skin
-
Synaptizine and Teporone now have OD threshold
-
Adds in berserker disease (treat with haloperidol)
-
Adds in Jenkem, a nasty gross drug made with toilet water
-
Adds in food poisoning; get it from eating poorly made food, from salmonella, or fungus
-
Adds in the Shock Revolver, a replacement for the stun revolver remove: removes the stun revolver remove: removes the prototype SMG+ammo from the protolathe
-
-
IK3I updated:
-
-
Can no longer holster items with No-Drop active.
-
Saves prosthesis users from Tox-Comp's wrath
-
-
KasparoVy updated:
-
-
Disembodied prosthetic heads that aren't monitors won't make you go bald when they're re-attached.
-
'Optic' markings will disappear when your head gets removed, and reappear if it gets re-attached.
-
Disembodied prosthetic heads that aren't monitors will now be rendered with hair & facial hair.
-
Disembodied prosthetic heads with optical markings (markings with the head set as the origin) will be rendered with those markings.
-
Animated hair styles (e.g. screens) and head accessories (e.g. 2/3 new antennae) will now be animated properly.
-
3 more antennae.
-
An alt. and monitor head model for every prosthetic brand but Zeng-hu. Morpheus only gets an alt model, not another monitor.
-
Animated optical markings to fit the new alt. heads.
-
Screen styles for the alt. Hesphiastos head.
-
Companies that make prosthetic body parts can (and do) now offer separate models for qualified recipients.
-
Removed the frames from screen styles in order to allow the same styles to be applied to all monitor heads.
-
-
LittleBigKid2000 updated:
-
-
Booze dispensers can now dispense synthanol
-
-
Norgad updated:
-
-
Adds a disposals chute to the Mechanic's Workshop
-
-
QuinnAggeler updated:
-
-
Adds the Drask as a 30KP race
-
Adds their language, Orluum
-
Adds a stylecolor for their language
-
Adds their butts (for photocopying)
-
Adds, at last, another race with skin tone (humies move over)
-
Adds a reason to make bad ice puns
-
Adds a check for brain death (brain damage of 120 or more) to the proc responsible for reviving IPCs
-
-
pinatacolada updated:
-
-
Makes fridge boards be selectable by screwdriving them
-
Virology fridge now accepts syringes, beakers, and bottles
-
Plasmamen security now spawn with their suit slot items in their bags
-
Pod pilots spawn with taser in the suit slot
-
removes armor from plasmamen magistrate suits
-
-
-
25 April 2016
-
CrAzYPiLoT updated:
-
-
Adds buildable holographic gameboards that, when opened, produce a fully-functional JavaScript chess interface, which includes a chess AI. If you win, it will produce 80 tickets for your spending!
-
-
FlattestGuitar updated:
-
-
a human's species is now visible on examination
-
-
Fox McCloud updated:
-
-
Improves attack animations with items, making it more clear who's attacking you and with what
-
Updates Revolution game mode so it better scales with total player population
-
Head revs start off with a flash, spraycan, and chameleon security HUD
-
Add chameleon security hud, which is basically sec shades with the ability to disguise as a number of regular glasses
-
Updates mining loot crates to feature far more actual loot
-
Mining loot crates are now opened by inputting a 4 digit password and have 10 tries to guess the password string
-
Fixes bees, mech syringes, and darts not properly calling INGEST for a reagent
-
-
Meisaka updated:
-
-
The light on/off function for drones works again, toggling between lowest setting and off.
-
Guardians can toggle their lights off and on again.
-
AI, pAI, robots and drones can now use *yes emote without extra ss on the end.
-
emote *help for silicons updated/added.
-
*twitch_s emote changed to *twitches, incorrect variations of some emotes can no longer be used.
-
-
tigercat2000 updated:
-
-
Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore"
-
You can now view HUD changes in real-time, by going to Preferences (top right tab) > Game Preferences and changing the HUD style (limited to humans).
-
There are now three HUD styles you can get via the f12 button- Full, which contains all of your buttons, Minimal, which only contains a few essential buttons, and None, which is a completely blank screen.
-
Removed the remaining aiming code due to maintainability issues and incompatibility with HUD styles.
-
Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if chain.
-
Refactored how objects (IE, stuff you pick up) is rendered to the HUD. This should fix the reoccuring "stuff on my screen that definately isn't meant to be there" bug, but keep an eye out for things that do not appear.
-
-
-
20 April 2016
-
Crazylemon64 updated:
-
-
Bureaucracy crates now contain granted and denied stamps.
-
-
FalseIncarnate updated:
-
-
Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code.
-
-
FlattestGuitar updated:
-
-
Adds shot glasses.
-
-
Fox McCloud updated:
-
-
Removes the ability to put a pAI into securitrons and ED-209's
-
Drinking glasses now have an in-hand sprite
-
DNA injectors no longer have a delay when used on yourself
-
DNA injectors no longer delete on use, but become used, much like auto-injectors
-
Fixes a bug where you can exploit the genetic scanner to get multiple injectors
-
Fixes not being able to cancel creating an DNA injector
-
remove spacesuits causing injections to the head to take longer
-
FIxes heat resist mutation not making you immune to high pressure, fire, or high temperatures
-
removes some not-well-known damage resists from cold/heat mutations
-
Re-maps botany a bit to make it more bee and botanist friendly
-
Adds in Abductors Game Mode
-
-
MarsM0nd updated:
-
-
Embeded object removal is now done with hemostat again
-
Borgs are able to do embeded object surgery
-
-
Tastyfish updated:
-
-
Makes the server startup substantially faster.
-
-
monster860 updated:
-
-
Crowbarring open a spesspod doors is no longer broken
-
-
tigercat2000 updated:
-
-
-tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!
-
-
-
14 April 2016
-
Aurorablade updated:
-
-
Removes the !!FUN!! of having headslugs gold core spawnable.
-
-
Fox McCloud updated:
-
-
Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
-
Added in sound for when airlocks deny access
-
cutting/pulsing wires will play a sound
-
ups nuke ops game mode population requirement from 20 to 30
-
Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
-
Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
-
Mining bots should be less likely to shoot you when attacking hostile mobs
-
Killer tomatoes actually live up to their name now and are hostile mobs
-
Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
-
Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
-
Increased the yield of regular tomatoes by 1
-
Tweak some stats on the killer tomato seeds
-
Fixes the blind player preference not doing anything
-
Adds portaseeder to R&D
-
Scythes will conduct electricity now
-
Mini hoes play a slice sound instead of bludgeon sound
-
Plant analyzer properly has a description and origin tech
-
Can have hulk+dwarf mutations together
-
Can have heat+cold resist together
-
Can only remotely view people who also have remote view
-
Fixes cold mutation not having an overlay
-
Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
-
Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
-
Fixes permanent nearsightedness even when wearing prescription glasses
-
-
KasparoVy updated:
-
-
Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
-
Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
-
-
Meisaka updated:
-
-
law manager no longer freaks out with Malf law
-
-
Tastyfish updated:
-
-
The /vg/ library computer interface has been ported, giving a much better use experience.
-
Books can now be flagged for inappropriate content.
-
-
TheDZD updated:
-
-
Removes shitty Caelcode bees.
-
Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
-
Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
-
Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
-
Added the ability to make Apiaries and Honey frames with wood
-
Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
-
Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
-
Removes some snowflakey mob behavior from bears, snakes and panthers.
-
Hudson is feeling punny.
-
Hostile mob AI should now be a bit more cost-efficient.
-
-
monster860 updated:
-
-
Adds area editing, link mode, and fill mode to the buildmode tool
-
-
-
12 April 2016
-
FalseIncarnate updated:
-
-
Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
-
Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
-
Burnt matches can no longer light cigarettes, pipes, or joints.
-
-
Fethas updated:
-
-
Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
-
You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
-
-
Fox McCloud updated:
-
-
Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
-
Vampires cannot use holoparasites
-
Malf AI will automatically lose if it exits the station z-level
-
-
Tastyfish updated:
-
-
All cats can kill mice now.
-
E-N can't suffocate.
-
Startup time is now shorter.
-
Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
-
-
-
07 April 2016
-
Crazylemon64 updated:
-
-
Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
-
Mulebots will now send announcements to relevant requests consoles on delivery again.
-
-
FalseIncarnate updated:
-
-
Adds logic gates, for doing illogical things in a logical manner.
-
Adds buildable light switches, for all your light toggling needs.
-
Fixes a resource duplication bug with mass driver buttons.
-
-
Fethas updated:
-
-
maybe makes them last longer...maybe..and fixes the event end message
-
-
Fox McCloud updated:
-
-
Maps in the slime management console to Xenobio
-
Reduces Xenobio monkey box count from 4 to 2
-
Fixes weakeyes having a negligible impact
-
Can spawn friendly animals with a new gold core reaction by injection with water
-
Hostile animal spawn increased from 3 to 5 for hostile gold cores
-
Swarmers, revenants, and morphs no longer gold core spawnable
-
Fixes invisible animal spawns from gold core/life reactions
-
Adds tape to the ArtVend
-
Can no longer use sentience potions on bots
-
Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
-
Slimecore reactions now require plasma dust as opposed to dispenser plasma
-
Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
-
Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
-
Epinephrine/plasma reagents changing mutation rate has been removed
-
Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
-
New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
-
Slime glycerol reaction removed
-
Slime cells are now high capacity cells (more power than before)
-
extract enhancer increases the slime core usage by 1 as oppose to setting it to three
-
slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
-
Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
-
Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
-
Processors no longer produce 1 more slime core than intended
-
Less blank/spriteless/empty foods from the silver core reaction
-
Virology mix reactions now use plasma dust as opposed to plasma
-
Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
-
statues are invincible to anything other than full out gibbing.
-
Statues flicker lights spell range increased
-
Blind spell no longer impacts silicons
-
Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
-
Fixes blind spell impacting the statue
-
-
Tastyfish updated:
-
-
Beepsky is no longer a pokemon.
-
pAI-controlled Bots now reliably speak human-understandable languages over the radio.
-
More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
-
-
tigercat2000 updated:
-
-
Items in your off hand will now count towards access.
-
-
-
02 April 2016
-
Crazylemon64 updated:
-
-
Metal foam walls will now produce flooring on space tiles
-
Syringes will now draw water from slime people.
-
-
FalseIncarnate updated:
-
-
Let's you know when your container is full when filling from sinks.
-
Prevents splashing containers onto beakers and buckets that have a lid on them.
-
Pill bottles can now be labeled with a simple pen.
-
Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
-
-
Fethas updated:
-
-
Various spells have had a tweak to stun/reveal/cast, some other number stuff...
-
Nightvision
-
harvest code is now in the abilites file.
-
New fluff objectives
-
Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
-
-
FlattestGuitar updated:
-
-
Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
-
-
Fox McCloud updated:
-
-
Adds in the Lusty Xenomorph Maid Mob; currently admin only.
-
Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
-
removes xenomorph egg from hotel
-
upgrades are no longer needed to for the available toys in the prize vendor
-
Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
-
Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
-
Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
-
Adds disease1 outbreak event
-
Adds appendecitis event
-
Roburgers now properly have nanomachines in them
-
Re-adds nanomachines
-
Experimentor properly generates nanomachines instead of itching powder
-
Fixes big roburgers having a healing reagent in them
-
Adds nanomachines to poison traitor bottles
-
Tajarans can now eat mice, chicks, parrots, and tribbles
-
Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
-
fixes spawned changeling headcrab behavior
-
-
KasparoVy updated:
-
-
Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
-
-
ProperPants updated:
-
-
Maint drones have magboots.
-
Removed plastic from maint drones. Literally useless for station maintenance.
-
Increased starting amounts of some materials for maint drones and engi borgs.
-
Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
-
Operating tables can be deconstructed with a wrench.
-
Fixed and shortened description of metal sheets.
-
-
Tastyfish updated:
-
-
Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
-
MULEbots can now access the engineering destination.
-
All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
-
Diagnostic HUD's now give health and status information about bots.
-
MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
-
Bots should (hopefully) lag the game less now.
-
Beepsky contains 30% more potato.
-
Action progress bars are now smooth.
-
Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
-
Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
-
Shuttle ETA countdowns on status displays are now amber.
-
pAI's can now use the PDA chatrooms.
-
Adds treadmills to brig cells, to give the prisoners something productive to do.
-
-
TheDZD updated:
-
-
A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
-
Removes that fucking facehugger from station collision.
-
-
tigercat2000 updated:
-
-
Virus2 has been removed.
-
Virus1 is back. Viva la revolution.
-
You can now have up to 20 characters.
-
-
-
26 March 2016
-
Fox McCloud updated:
-
-
Adds in dental implant surgery. Implant pills into people's teeth.
-
Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
-
Robotics now has a "sterile" surgical area for performing augmentations
-
Adds the FixOVein and Bone Gel to the autolathe
-
ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
-
-
KasparoVy updated:
-
-
Slime People can now wear underwear.
-
Slime People can now wear undershirts.
-
-
TheDZD updated:
-
-
NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
-
After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
-
-
-
25 March 2016
-
Crazylemon64 updated:
-
-
You now will actually have the correct `real_name` on your DNA.
-
No more roundstart runtimes regarding IPC hair.
-
Mitocholide rejuv will work more usefully now.
-
Limbs and cyborg modules will no longer appear in your screen.
-
Cyborg module icons are now persistent throughout logging in and out.
-
Various cyborg modules, like engineering, now use the proper icon.
-
-
FlattestGuitar updated:
-
-
Adds confetti grenades.
-
-
Fox McCloud updated:
-
-
Fixes Sleeping Carp combos not having an attack animation
-
Fixes several chems not properly healing brute/burn damage, consistently, as intended
-
-
KasparoVy updated:
-
-
Unbranded heads and groins no longer invisible.
-
Zeng-hu left leg will now be in line with the body when facing south.
-
-
-
22 March 2016
-
Crazylemon64 updated:
-
-
Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
-
Makes heads keep hair on removal
-
Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
-
Wounds will vanish on their own now
-
Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
-
Fixes a runtime regarding failing a limb reconnection surgery
-
Copying a client's preferences now overrides the previous mob's DNA
-
A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
-
DNA-lacking species can no longer be DNA-injected
-
Brains are now labeled again
-
Splashing mitocholide on dead organs will make them live again.
-
The body scanner now detects necrotic limbs and organs.
-
pAIs and Drones are now affected by EMPs and explosions while held.
-
-
Fethas updated:
-
-
Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
-
fixes a dumb error in internal bleeeding surgerys
-
Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
-
-
FlattestGuitar updated:
-
-
Adds a snow, navy and desert military jacket.
-
-
Fox McCloud updated:
-
-
Removes random 1% chance to heal fire damage
-
Removes passive healing from resist heat mutation
-
Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
-
Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
-
Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
-
Changes Outpost Mass Driver to prevent accidental spacings
-
Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
-
Shadowlings no longer get hungry or fat and no longer dust on death
-
-
KasparoVy updated:
-
-
The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
-
Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
-
Faux-eye optics for non-Morpheus heads.
-
The ability to change optic (eye) colour if you've got a non-Morpheus head.
-
The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
-
Two hair styles from Polaris.
-
The ability for IPCs to wear undergarments (shirts and trousers).
-
Antennae (colourable) for IPCs.
-
IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
-
Combat/SWAT boots can now be toecut and jacksandals can't.
-
ASAP fix to what would've broken the ability to configure prostheses in character creation.
-
Adjusted masks no longer block CPR (including bandanas).
-
You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
-
-
Regens updated:
-
-
Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
-
Assisted organs will now also take damage from EMP's
-
Internal robotic and assisted organs will now actually take damage from EMP's
-
-
Tastyfish updated:
-
-
Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
-
You can now set the PDA messenger to automatically scroll down to new messages.
-
Pet collars now act as death alarms and can have ID's attached to them.
-
All domestic animals can now wear collars.
-
You can now make video cameras at the autolathe.
-
-
TheDZD updated:
-
-
Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
-
-
TravellingMerchant updated:
-
-
Kidan have new sprites!
-
-
tigercat2000 updated:
-
-
Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
-
Lighting overlays can no longer go below 0 lum_r/g/b
-
Shuttles will work with lighting better.
-
Wizards can no longer teleport to prohibited areas such as Central Command.
-
-
-
16 March 2016
-
Crazylemon64 updated:
-
-
Being in godmode now makes you immune to bombs
-
Science members now get compensated when they ship tech disks to centcomm.
-
Science crew are no longer paid when they "max" research.
-
Roboticists now get credit for making RIPLEYs and Firefighters
-
Slime people can now regrow limbs on a more lax nutrition requirement
-
Enhances the nutripump+ to let slime people regrow limbs with it active
-
Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
-
Rejuvenating a slime person will no longer clog up their "blood"
-
Slime people will now regenerate "blood" from having water in their system
-
The decloner can now be created again
-
Environment smashing mobs can now destroy girders.
-
-
DaveTheHeadcrab updated:
-
-
Removes the check for species on the update_markings proc.
-
-
FalseIncarnate updated:
-
-
Xeno-botany is now more user-friendly, and less random letters/numbers.
-
Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
-
You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
-
-
Fethas updated:
-
-
Syringes are no longer sharp
-
byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
-
fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
-
nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
-
Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
-
Hopefully fixes issues with diona eyes
-
Though shalt not eat robotic organs..including cybernetic implants..
-
ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
-
-
FlattestGuitar updated:
-
-
Adds three new synthanol drinks
-
Drinking synthanol is now a bad idea if you're organic
-
A glass of holy water now looks like normal water
-
-
Fox McCloud updated:
-
-
Adds in drink fizzing sound
-
Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
-
Adds in a fuse burning sound
-
Bath salts, black powder, saltpetre, and charcoal use this sound now
-
Adds in a matchstrike+burning sound
-
Lighting a match triggers this new sound
-
Adds in scissors cutting sound
-
Cutting someone's hair uses this new sound
-
Adds in printer sounds
-
printing off papers from various devices typically uses these sounds
-
Adds computer ambience sounds
-
black box recorder and R&D core servers both play this sound at random rare intervals
-
Reduces the tech level (and requirement) for nanopaste
-
Reduces the tech level (and requirement) for the plasma pistol
-
Removes Nymph and drone tech levels
-
Reduces tech levels on the flora board
-
Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
-
Increases tech cost of the decloner
-
Removes the pacman generators
-
Removes emitter
-
Removes flora machine (functionless anyway)
-
Removes the pre-spawned nanopaste
-
Removes space suits
-
Removes excavation gear
-
Replaces the soil with actual hydroponic trays (more aesthetic than anything)
-
Removes most external asteroid access from the station
-
Excavation storage is now generic science storage
-
removed the plasma sheet
-
Fixes augments not showing up in R&D unless specifically searched for
-
Fixes some augments being unavailable in mech fabs
-
Fixes augments having no construction time
-
Fixes xenos not gaining plasma when breathing in plasma
-
Fixes plasma reagent not generating plasma for a person
-
Screaming has different sounds based on being male or female
-
Implements Goon's screaming sounds.
-
Screaming tone is now based on age of character instead of being random
-
Ups the cooldown on screaming from 2 seconds to 5 seconds
-
Removes chance for Whilhelm scream
-
Borgs can now scream
-
Monkey's now have a unique screaming sound
-
IPCs now scream like cyborgs
-
Updates slot machines to have higher jackpots and more payouts with more interesting sounds
-
Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
-
tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
-
Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
-
Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
-
Chemist warddrobe now has two gas masks
-
Teslium will now impact synthetics AND organics
-
Fixes facehuggers hugging already infected people
-
Fixes facehuggers hugging people while dead
-
Fixes Embryo's developing twice as fast as they should
-
Fixes up some behaviors with xeno eggs
-
Xeno acid can now melt through floors and the asteroid
-
Xeno's now play the gib sound when actually gibbed
-
Implements Changeling headcrabs/headspiders
-
Fixes xenos not throwing their organs when gibbed
-
Fixes swallowed mobs not being ejected when a human is gibbed
-
Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
-
Fixes EMPs causing eye implant users to be permanently blind
-
Increases bag of holding's storage capacity
-
Removing a heart no longer kills the patient instantly, but induces a heart attack
-
Demon hearts will not work
-
Should now actually be able to re-insert hearts
-
Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
-
changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
-
sleepers help you recover from addiction faster
-
Can now make cable coils in autolathes
-
Fixes the slot machine announcements not displaying properly
-
-
Tastyfish updated:
-
-
The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
-
Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
-
Cloning a vampire no longer makes them lose their abilities.
-
Vampires can no longer hypnotize chaplains.
-
Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
-
Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
-
Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
-
-
monster860 updated:
-
-
Mining station now has a podbay.
-
Ore scooping module for the spacepod.
-
Three mining lasers for spacepod: Basic, normal, and burst.
-
Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
-
-
taukausanake updated:
-
-
Mice can now be picked up like diona
-
-
-
08 March 2016
-
Crazylemon64 updated:
-
-
Slime people are now more vulnerable to low temperatures.
-
Slime people are able to slowly regrow limbs at a high nutrition cost.
-
Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
-
Slime people's cores are more vulnerable to damage
-
Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
-
-
Fethas updated:
-
-
the nest buckle now looks for the right organ path
-
Fixed some sprites.
-
No more putting no drops in rechargers,
-
-
Fox McCloud updated:
-
-
Implement's goon's gibbing sound
-
Implement's goon's gibbing sound for robots/silicons
-
Removes old gibbing sound
-
-
Spacemanspark updated:
-
-
Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
-
-
Tastyfish updated:
-
-
Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
-
There are also permanent invisible walls and silent floors that can be made from tranquillite.
-
The Recitence mech is now buildable!
-
The Recitence mech is now playable!
-
Mid-round selection for various creatures and antagonists now consistently asks permission.
-
-
TheDZD updated:
-
-
Adds justice helmets with flashing lights and annoying sirens.
-
Adds crates containing said helmets.
-
Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
-
-
monster860 updated:
-
-
Space pod transitions are now fixed.
-
-
-
07 March 2016
-
Crazylemon64 updated:
-
-
People with VAREDIT can now write matrix variables
-
People with VAREDIT can now modify path variables
-
Refactors the variable editor code somewhat.
-
The buildmode area tool now shows reticules of what you've selected.
-
Switching mobs while using the buildmode tool no longer screws up your UI.
-
Refactors buildmode so it's no longer a special-case system.
-
Adds a copy mode to build mode, which lets you duplicate objects.
-
Any mob in buildmode can work at the fastest possible rate.
-
Fixed a problem where the icons of a person would not correctly update when changing gender.
-
One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
-
Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
-
You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
-
Your organs will now match your gender when you are cloned.
-
Skeletons (when a body rots) no longer retain a fleshy torso.
-
Putting people in an active cryotube now produces the message on insertion, rather than release.
-
An EMP'd cloning pod will now display its sprites correctly.
-
-
FalseIncarnate updated:
-
-
Water Balloons can be filled from more sources than just beakers and watertanks.
-
-
Fox McCloud updated:
-
-
Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
-
Noir mode only activates when the glasses are equipped to your actual eyes
-
Noir Glasses mode can be toggled on or off (defaults to off)
-
Mimes can no longer use spells and continue speaking
-
Mime abilities are now spells with proper icons
-
Mime wall now last 30 seconds, up from 5
-
forecfields/invisible walls now block air currents
-
Adds the Sleeping Carp scroll to the uplink for 17 TC
-
Fixes Shadowlings being able to use guns
-
Fixes sleeping carp scroll users being able to use guns
-
Fixes the Experimentor throwing one item at a time
-
Experimentor menu now automatically refreshes after use
-
Lowers surgery times across the board
-
Removes scalpels causing 1 damage on successful surgery
-
Removes random chance to fracture ribs on a successful surgery
-
Mining drills now have an edge
-
-
KasparoVy updated:
-
-
Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
-
You can now adjust breath masks while buckled into beds and chairs.
-
Known issues with adjusted jackets using the wrong sprites.
-
Blueshield coat in hand and item icons.
-
Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
-
-
Tastyfish updated:
-
-
Infrared emitters can now be rotated while already in an assembly via the UI popup.
-
The infrared emitter can no longer be hidden inside of boxes and still work.
-
The beach now has a border and is splashier.
-
Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
-
Gives the Librarian / Jouralist a multicolored pen.
-
Gives the NT Representative a clipboard.
-
The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
-
-
VampyrBytes updated:
-
-
Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
-
Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
-
-
-
26 February 2016
-
FalseIncarnate updated:
-
-
Chocolate can now make you fat, as expected.
-
-
Fox McCloud updated:
-
-
stamina damage now regenerates slightly faster
-
Adds in whetstones for sharpening objects
-
Kitchen vendor starts off with 5 salt+pepper shakers
-
Can now point while lying or buckled
-
Fixes Capulettium Plus not silencing
-
Fixes slurring, stuttering, drugginess, and silences last half of what they should
-
-
KasparoVy updated:
-
-
Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
-
-
Spacemanspark updated:
-
-
Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
-
-
Tastyfish updated:
-
-
Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
-
-
-
24 February 2016
-
Crazylemon64 updated:
-
-
The defib should be more reliable on people who have ghosted
-
The defib will now give a message if the ghost is still haunting about
-
Attacking someone with an accessory will now let you put things on them without having to strip them.
-
Borers will now properly detach upon death of a mob they are controlling
-
Borers can now see their chemical count while in control of a mob
-
Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
-
Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
-
Borers infesting and hiding are now silent.
-
Made borer's chem lists more nicely formatted
-
No more superspeed attacking simplemobs
-
New players now show up properly under the "who" verb when used as an admin
-
Mining drones will now automatically collect sand lying around
-
RIPLEYs can now drill asteroid turfs for sand
-
You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
-
You can now load the fuel generators from an ore box.
-
The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
-
You can now light cigarettes off of burning mobs.
-
Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
-
Miners can now collect ore by walking over it with an ore satchel on.
-
-
FalseIncarnate updated:
-
-
Adds prize tickets as a replacement for physical arcade prizes.
-
Adds a buildable prize counter to exchange tickets for prizes.
-
Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
-
Adds colorful wallets, for that old school arcade pride.
-
Fixes accidental removal of plump helmet biscuit recipe.
-
Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
-
Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
-
-
FlattestGuitar updated:
-
-
Adds IPC alcohol and a few derivative drinks
-
IPCs can now drink and be fed from glasses
-
-
Fox McCloud updated:
-
-
Laser eyes mutation no longer drains nutrition
-
splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
-
nerfs heart attacks so they do less damage
-
Pickpocket gloves now put the item you strip into your hands as opposed to the floor
-
Picketpocket gloves can now silently strip accessories
-
Pickpocket gloves will no longer give a message for messing up a pickpocket
-
-
KasparoVy updated:
-
-
Adjusting masks while they are not on the face will no longer turn off internals.
-
Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
-
Adds the ability to open/close bomber jackets.
-
Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
-
Adds UI button in top left of screen for jacket adjustment.
-
Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
-
Centralizes jacket/coat adjustment handling.
-
All jackets start closed by default.
-
Geneticist duffelbag on-mob sprite (for all species).
-
Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
-
Refactors back-item icon generation.
-
Typo in the description of Santa's sack.
-
Missing punctuation and gender macros in the description of the bag of holding.
-
The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
-
-
PPI updated:
-
-
Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
-
-
Regen1 updated:
-
-
Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
-
-
Spacemanspark updated:
-
-
Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
-
-
Tastyfish updated:
-
-
The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
-
All of the heads now have multicolored pens.
-
EngiVend now has 10 camera assemblies.
-
Borgs can now use vending machines.
-
There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
-
-
pinatacolada updated:
-
-
Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
-
-
ppi updated:
-
-
When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
-
-
-
13 February 2016
-
Crazylemon64 updated:
-
-
Relaxes the check on what atoms you can follow to any movable atom
-
Mages are now more ragin
-
Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
-
-
DaveTheHeadcrab updated:
-
-
Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
-
-
FalseIncarnate updated:
-
-
Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
-
Adds chimichangas. You know you want a deep-fried burrito.
-
-
Fox McCloud updated:
-
-
Updates some spell icons with better/higher quality icons
-
Updates unarmed attacks to allow for more customization
-
Updates martial arts so they factor in specie's attack messages and sounds
-
Re-balances Sleeping Carp fighting style
-
Re-balances Bo Staff
-
Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
-
Fixes Ei Nath generating two brains
-
Ensures the Necromatic Stone generates actual skeletons
-
Can now strip PDA/IDs from Golems
-
Fixes sleeping carp grab not being an instant aggressive grab
-
Fixes an exploit with declaring war on the station
-
-
KasparoVy updated:
-
-
Orange and purple bandanas for all station species.
-
The ability to colour bandanas with a crayon in a washing machine.
-
Refactors the bandana adjustment system.
-
Minor adjustments to Tajaran and Unathi bandana east/west sprites.
-
Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
-
Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
-
Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
-
Greys now use re-positioned smokeables. They no longer smoke out the eyes.
-
-
TheDZD updated:
-
-
Fixes spacepods being able to shoot through walls.
-
Lowers spacepod weapons fire delay.
-
Increases spacepod weapons energy costs.
-
Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
-
Reduces battery costs for spacepod movement.
-
-
-
10 February 2016
-
Crazylemon64 updated:
-
-
The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
-
A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
-
Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
-
Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
-
Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
-
Adds a reagent system for species reacting to specific reagents
-
Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
-
Increases the frequency of the cortical borer event.
-
People with borers cannot commit suicide - this applies to a controlling borer, too.
-
Borers can no longer overdose their hosts.
-
Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
-
A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
-
Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
-
You can now gib butterflies and lizards with a knife
-
Ghosts can now follow mecha
-
You can now access an R&D console by emagging it - it did nothing before.
-
Walls will now properly smooth and show damage.
-
Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
-
-
Fox McCloud updated:
-
-
Fixes not being able to attach IEDs to beartraps
-
Can no longer spamclick someone to death using headslamming on a toilet/urimal
-
Toilet/urinal headslamming now plays a sound
-
Toilet headslamming damage reduced slightly
-
Can now fill open reagent containers in a toilet to receive "toilet water".
-
No more message spam when someone fills a container using a sink
-
Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
-
Washing things will now use progress bars
-
Ensures consuming a single syndicate donk pocket won't get you addicted to meth
-
Kinetic Accelerators and E-bows automatically reload
-
-
Glorken updated:
-
-
Added a Knight Arena for Holodeck.
-
Added red and blue claymore sprites.
-
Changed overrided to overrode when emagging Holodeck computer.
-
-
KasparoVy updated:
-
-
Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
-
Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
-
Warden now gets their own version of the SWAT sechailer in their locker.
-
HOS now gets the appropriate version of the SWAT sechailer in their locker.
-
Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
-
Minor adjustments to Tajaran breath mask up-state sprites.
-
-
PPI updated:
-
-
Adds a reconnect button to the File menu in the client.
-
Adds head patting
-
-
Regen updated:
-
-
Powersink can now drain a lot more power before going boom
-
Buffed the powersinks drain rate
-
Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
-
Admin log warning before the powersink explodes
-
-
Spacemanspark updated:
-
-
Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
-
Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
-
-
Tastyfish updated:
-
-
Species that don't breathe can kill themselves now!
-
Suicide messages are now catered to your species.
-
Shortened the default pill & patch name when using the ChemMaster.
-
The chaplain now has a service radio headset, as Space Jesus intended.
-
-
TheDZD updated:
-
-
When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
-
Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
-
Adminhelps and PM replies from admins appear in a bold bright red color.
-
PM replies from players appear in a dull/dark purple color.
-
Adds admin attack log to players being converted to cult.
-
Adds shadowling thrall jobbans.
-
Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
-
-
-
31 January 2016
-
Crazylemon64 updated:
-
-
Syndicate borgs can now interact with station machinery
-
People with slime people limbs can now *squish
-
Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
-
-
FalseIncarnate updated:
-
-
Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
-
Adds in the Magic Conch Shell, an admin-only shell of power.
-
-
Fox McCloud updated:
-
-
Updates Summon Guns and Magic to include many of the new guns
-
Summon Guns/Magic can no longer be used during Ragin' Mages
-
-
Tastyfish updated:
-
-
The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
-
Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
-
-
pinatacolada updated:
-
-
Adds NanoUI to the operating computer
-
Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
-
-
-
29 January 2016
-
Crazylemon updated:
-
-
The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
-
Matter eater now allows you to eat humans as if you were fat.
-
Eating mobs with an aggressive grab now generates attack logs.
-
-
Crazylemon64 updated:
-
-
For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
-
Ghosts can now see the contents of smartfridges and look at the drone console
-
Humans now only produce one message when shaken while SSD
-
The supermatter no longer will irradiate everyone, everywhere, when it explodes.
-
Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
-
Brains are no longer able to escape their brain by being a sorcerer.
-
Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
-
Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
-
-
FalseIncarnate updated:
-
-
Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
-
-
Fox McCloud updated:
-
-
Fixes mutadone not working with some genetic mutations
-
Fixes banana honk and silencer being alcoholic
-
Fixes Kahlua being non-alcoholic
-
Fixes polonium not metabolizing
-
Fixes being able to receive free unlimited boxes from the Merchandise store
-
Adds in wooden bucklers
-
Re-adds roman shield to the costume vendor
-
Buffs Riot shield damage from 8 to 10
-
Adds in a Skeleton race
-
Tweaks the skeletons colors to be more realistic and to blend in less with the floor
-
Adds in lichdom spell for the wizard
-
Adds in lesser summon guns spell for wizard
-
adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
-
Wizard can purchase the charge spell from the spell book
-
Wizard can purchase a healing staff from the spell book
-
Tweaks and lowers spell costs of utility spells for wizard
-
Re-organizes the spellbook to be better divided into categories and have a better window size
-
Knock now opens+unlocks lockers
-
Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
-
-
KasparoVy updated:
-
-
Navy blue Centcom Officer's beret for use by the Blueshield.
-
Adds the new navy blue beret to the Blueshield's locker.
-
Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
-
Adds TG energy katana back and belt sprite.
-
Bo staff back sprite.
-
Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
-
Cutting open the toes of footwear so species with feet-claws can wear them.
-
Toeless jackboots.
-
Cleans up glovesnipping and lighting a match with a shoe.
-
Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
-
-
Tastyfish updated:
-
-
Cargonia now has its own section in the manifest.
-
-
TheDZD updated:
-
-
Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
-
-
-
24 January 2016
-
KasparoVy updated:
-
-
Fixes markings overlaying underwear.
-
Nude icon in underwear.dmi
-
Fixes Vox robes not using the correct on-mob sprites.
-
Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
-
Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
-
-
Tastyfish updated:
-
-
Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
-
-
-
23 January 2016
-
Fox McCloud updated:
-
-
Removes Vampire HUD
-
moves the Vampire blood counter to a more easy to see location
-
Adds in a Changeling chemical counter display
-
Adds in a Changeling sting counter display
-
Vampire total blood and usable blood will now appear under status
-
Changes vampire blood display to be similar to ling chemical counter
-
Fixes unnecessary toxin damage being dealt on severe bloodloss
-
Fixes human mobs not receiving proper random names
-
Adds in knight armor
-
Grants the chaplain a set of crusader knight armor
-
Adds in cult-resistant ERT paranormal space suit
-
Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
-
Chaplain's closet is now a secure closet
-
Adds in Assault Gear crate to cargo
-
Adds in military assault belt
-
Adds in spaceworthy swat suits
-
tweaks bandolier to hold 2 additional shotgun shells
-
bartender starts off with +2 additional shells
-
Reduces the cost of the space suit crate and doubles its contents
-
Refactors knives so their behavior is more universal
-
Fixes Hulk not properly being removed when your health drops below a threshold
-
Fixes flickering vision in a mining mech
-
-
Tastyfish updated:
-
-
Poly has taken a seminar on the latest trends in engine operations.
-
Player-controller parrots can now hear their headsets.
-
-
Tigerbat2000 updated:
-
-
The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
-
Cultists can once again actually greentext the escape objective.
-
-
-
20 January 2016
-
DarkPyrolord updated:
-
-
Adds in hardsuit sprites for Vulpkanin
-
-
FalseIncarnate updated:
-
-
Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
-
Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
-
-
Fox McCloud updated:
-
-
Fixes brute damage on weapons not knocking people down.
-
Tweaks implant behavior to be more consistent and unified.
-
Lowers the pAI cooldown from 60 seconds to 5 seconds.
-
Raw telecrystal can now be used to charge uplink implants.
Vulpkanin hardsuit helmets with proper flashlight-on sprites.
-
-
Tastyfish updated:
-
-
The ID computer Access Report printout now separates the access list with commas so it's actually readable.
-
The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
-
In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
-
Table flipping uses correct sprites.
-
-
TheDZD updated:
-
-
Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
-
-
-
18 January 2016
-
Crazylemon updated:
-
-
New classes of shapeshifters have been sighted around the NSS Cyberiad...
-
Wizards now can't teleport to other antag spawn points.
-
Removes an extruding pixel from the left-facing IPC glider monitor sprite.
-
Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
-
Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
-
It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
-
-
Dave The Headcrab updated:
-
-
Adds the advanced energy revolver, toggles between taser and laser modes.
-
Removes the detective's revolver from the blueshield's locker.
-
Changes the taser the blueshield starts with into an advanced energy revolver.
-
-
Deanthelis updated:
-
-
Added the ability for the Magnetic Gripper to pick up and place light tiles.
-
-
Fethas updated:
-
-
Readds the hud icon showing up for master and servent
-
adds mindslave datum hud thingy based on TGs gang huds
-
-
Fox McCloud updated:
-
-
Fixes not being able to add/remove Weapon Permit from IDs.
-
Fixes the energy sword being invisible in-hand when turned on.
-
Fixes the telebaton being invisible in-hand when extended.
-
Fixes eye-stabbing not having an attack animation or hitsound.
-
Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
-
Fixes the butcher cleaver sprite being backwards.
-
Fixes the telebaton sprite being missing from the side.
-
Fixes the meat cleaver being invisible in-hand.
-
Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
-
completely overhauls implants to TG's standards.
-
Adds storage implant.
-
Adds microbomb and macrobomb implants.
-
Adds in support for removing implants directly into cases.
-
Removes Bay style explosive implants.
-
Removes compressed matter implants.
-
Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
-
Fixes/cuts down on the lag caused by monkey cubes.
-
-
Jey updated:
-
-
Inflatable walls and door can now be deflated by altclicking them
-
Fixed lag from expanding multiple monkeycubes at once.
-
-
KasparoVy updated:
-
-
Adds blank icons with standardized timings for species tail wagging, used in icon generation.
-
Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
-
Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
-
Tails now appear in ID cards, overlays things correctly.
-
Tails now overlay and are overlaid by things correctly in preview icons.
-
Modifies the positioning of tail icon generation in the ID card preview icon generation file.
-
Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
-
Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
-
If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
-
Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
-
Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
-
Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
-
Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
Adjusts NV science goggles object icon. Removed strange border and centered it.
-
Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
-
-
Kyep updated:
-
-
Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
-
Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
-
-
NTSAM updated:
-
-
Added a rainbow IPC screen.
-
-
PPI updated:
-
-
Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
-
-
Tastyfish updated:
-
-
The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
-
New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
-
Fixed a few maintenance door names to be in parity to the rest of the station.
-
Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
-
-
Tigercat2000 updated:
-
-
You can no longer use the gibber for monkies.
-
Cleaned up gibber.dm styling.
-
The fire alarm now uses NanoUI, with color coded alert levels.
-
Upgraded NanoUI (again), fancy FontAwesome icons.
-
Didn't add any butts. Yet.
-
-
-
13 January 2016
-
Fox McCloud updated:
-
-
Fixes Rezadone not clearing mutated organs.
-
Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
-
Explosions will no longer destroy things underneath turfs until the turf is exposed.
-
fixes a runtime related to revolver spinning.
-
fixes server loading taking an abnormally long time.
-
-
Kyep updated:
-
-
Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
-
-
Tastyfish updated:
-
-
NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
-
-
-
11 January 2016
-
CrAzYPiLoT updated:
-
-
Fixes the footsteps sounds to the fullest.
-
-
Crazylemon updated:
-
-
Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
-
Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
-
Bomb guardians now are more aware of what is primed to explode.
-
Bomb guardian summoners can now defuse their guardian's bombs without harm.
-
Brought RAGIN' MAGES back up to function.
-
-
Dave The Headcrab updated:
-
-
Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
-
-
Fox McCloud updated:
-
-
Re-arranges the armory and changes its contents minorly.
-
Adds in rubbershot ammo boxes.
-
Fixes Mutadone incurring a massive cost on the server.
-
Positronic brains can no longer speak binary.
-
Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
-
IPC's positronic brains start off toggled off.
-
Fixes the supermatter announcement causing massive amounts of server lag.
-
Adds in tradable telecrystals.
-
-
-
08 January 2016
-
Crazylemon updated:
-
-
Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
-
IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
-
Sleepers and Body Scanners will now reliably work when rotated
-
SSD humans should be asleep more reliably now.
-
-
Dave The Headcrab updated:
-
-
Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
-
Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
-
Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
-
Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
-
Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
-
-
FalseIncarnate updated:
-
-
Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
-
Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
-
Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
-
-
Fethas updated:
-
-
Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
-
-
Fox McCloud updated:
-
-
fixes a bug relating to some brute/burn damage being dealt to human mobs.
-
Adds in overloading APCs, causing them to arc electricity to mobs in range.
-
Makes Engineering related APCs overload proof.
-
Implements the timestop spell.
-
Implements new sepia slime reaction which halts time in an AoE.
-
sentience potions no longer can make slimes sentient.
-
Removes Hulk instant stun.
-
Hulk damage increased.
-
Hulk wears off at a lower health threshold.
-
Fixes strange reagent not working on simple animals.
-
Reduces the amount shock damage and bounces for the Tesla engine.
-
Fixes Syndicate Cyborg's LMG being invisible.
-
Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
-
-
KasparoVy updated:
-
-
Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
-
Removed a duplicate of the human balaclava sprite.
-
Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
-
-
Tastyfish updated:
-
-
Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
-
-
Tigercat2000 updated:
-
-
Added 96x96 (3x) res option to icons menu
-
-
-
06 January 2016
-
Certhic updated:
-
-
Corrected some air alarms so that atmos computer can access them
-
Bodyscanner now sees mechanical parts in internal organs
-
-
Crazylemon64 updated:
-
-
Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
-
-
Tastyfish updated:
-
-
Instruments now use NanoUI.
-
Corrected the blueshield mission briefing.
-
-
-
03 January 2016
-
TheDZD updated:
-
-
Ports over changelog system from /tg/station.
-
-
-
-GoonStation 13 Development Team
-
- Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
- Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
-
+ Current Project Maintainers:-Click Here-
+ Currently Active GitHub contributor list:-Click Here-
+ Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
+ Spriters: FullOfSkittles
+ Sounds:
+ Main Testers: Anyone who has submitted a bug to the issue tracker
+ Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image. Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
+ Have a bug to report? Visit our Issue Tracker.
+ Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred.
+
+
+
+
+
+
+
+
26 April 2020
+
Cazdon updated:
+
+
Admin Roles no longer appear on manifest.
+
Central Command PDA's no longer appear on the messenger list.
+
Potential Convertee's being unable to be converted.
+
+
Drakeven updated:
+
+
Fixed mislabeled traitor and mindslave special role.
+
+
Ionward updated:
+
+
Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific fits for soft space suits.
+
Vox can now wear soft space suits, such as EVA (Clown and Mime included), NASA Void, and Syndicate suits.
+
Added Vox soft suit sprites.
+
+
JKnutson101 updated:
+
+
Combined the Rite of Tribute and Rite of Enlightenment into one Rite of Offering.
+
Sacrificing now properly puts victims that have at one point had CKeys into soul stones, or polls dead-chat to do so.
+
+
Kyep updated:
+
+
Tweaked Greater Hellhound, added more non-violent options and one unique combat spell.
+
+
SteelSlayer updated:
+
+
Fixes the "List SSDs and AFKs panel" showing everyone as the target of an assassinate objective
+
The global objectives list is now viewable in the MC Globals menu
+
Reverts some terrible changes that are causing some bugs with traitors
+
Fixes AIs with the combat module not being able to hack APCs
+
+
TDSSS updated:
+
+
duplicate mecha definitions
+
blobbernaut vision blur now clears as intended.
+
fixed a bug preventing ticket system from working under some circumstances.
+
+
VeteranKyl updated:
+
+
DNA Samplers now check if the target species has DNA.
+
Fixed the envenomed blob's spore toxin not causing harm.
+
+
craftxbox updated:
+
+
fixed colors not working without regex
+
fixed text panel not loading when an invalid regex is added
+
polyfilled string.prototype.includes
+
+
moxian updated:
+
+
being in a locker no longer interferes with tracking implant tracking
+
locator no longer locates tracking implants on other z levels.
+
fixed singulo being unable to expand when placed next to containment wall
+
+
+
27 October 2019
+
AdamElTablawy updated:
+
+
Xenobiology can no longer produce hellhounds with gold slime cores.
+
+
AzuleUtama updated:
+
+
Vampire's shape shift ability and DNA scrambler item now clear flavour text on use.
+
+
Darkmight9 updated:
+
+
Adds a wide variety of craftable decorations! You can find them in the new 'Decorations' tab in the crafting menu.
+
tweaked the duct tape component so that you can now add it to items to make them naturally stick to walls.
+
added decorative sprites.
+
+
Fox McCloud updated:
+
+
windows are easier to break
+
Adds in the Rod of Asclepius, a healing item that carries an immense burden
+
Fixes Bubblegum spawning being ridiculously rare
+
Fixes planetary atmos not correctly happening
+
Fixes atmos pipe unwrenching
+
Survival pod medical vendors only have 2 pairs of splints instead of a wide array of medicines
+
Hivelord core, when used on someone, no longer fully revives them; instead it heals 25 burn, 25 brute, resets body temperature, removes all CC, cures all internal bleeding, and mends all fractures (slowdown bonus still stays
+
updates the close icon for storage to not be a trashy codersprite
+
Fixes excessive mob and tendril clumping on Lavaland
+
Fixes being able to exploit the destructive analyzer for unlimited materials
+
Fixes Hierophant arena atmos
+
+
Ionward updated:
+
+
fixed Battlemage armor having an unintended helmet light
+
added Vox versions of Battlemage, Paranormal, Inquisitor, Berserker, and Syndicate Elite Hardsuits.
+
+
SteelSlayer updated:
+
+
Fixes the RPED and bluespace RPED not displaying a list of parts in players chat when used on a machine
+
+
TDSSS updated:
+
+
yellow documents are no longer indestructible.
+
+
Tayyyyyyy updated:
+
+
single quotes showing up weird in names and announcement titles
+
+
Terilia updated:
+
+
Headcrab Nests
+
Headcrabs can now eat dead simple_animal corpses to regain 10 hp.
+
Poison Headcrabs will not inject LSD anymore.
+
Headcrabs have more HP and some do more damage.
+
Headcrabs will not stop attacking people after they are unconscious.
+
Headcrab Nest DMI
+
+
Ty-Omaha updated:
+
+
Admin attack log level of heirophant club updated
+
+
actioninja updated:
+
+
Nanoui interfaces in fancy mode now open more cleanly
+
+
craftxbox updated:
+
+
Vanilla JS Regex for chat highlighting
+
Removed jquery mark
+
quickfix to stop people using the scanner inside it
+
+
farie82 updated:
+
+
Cult whispering now uses your real name
+
Fixed the invisible blob zombies
+
A runtime in blob/factory/run_action
+
+
+
13 October 2019
+
Darkmight9 updated:
+
+
Re-added the handheld defib sprites
+
+
Fox McCloud updated:
+
+
Fixes wrench attacking telepads
+
performance improvements for xenobio stuff
+
LINDA is much more aggressive at distributing gas between turfs in an excited group
Reverted autoban using legacy system causing issues
+
+
streather updated:
+
+
fixed a typo in the autolathe
+
+
+
09 October 2019
+
Darkmight9 updated:
+
+
Gives the handheld defib a new sprite
+
+
Fox McCloud updated:
+
+
DNA vault requires 5 pico manipulators and 5 super capacitors instead of quadratic capacitors
+
Powers of the DNA vault adjusted
+
DNA vault no longer allows you to have unlimited genetics powers.
+
All previous powers removed with the exception of no breathing
+
New powers: breathable plasma immunity+virus immunity, heat immunity+burn reduction, speed increase, species armoring+pierce immunity, stun reduction, and action speed increase
+
Removes consoles screens; use plane old glass in place of them. Holy sheet, they were a pane.
+
Adds being able to make leather with the bio-generator
+
removed a lot of leather-related recipes from the bio-generator; these have been moved to leather crafting
+
can make hide mantles with leather
+
wearing pants while wearing an undershirt means your arms and chest are covered
+
Fixes AI swarmers not doing anything
+
swarmers can eat circuitboards and their own shells now
+
Fixed being able to eat soil
+
de-activated swarmer shells give 10,000 metal and 4,000 glass instead of 100 metal and 400 glass.
+
Fixes lavaland swarmers not being able to teleport people away
+
Swarmers can place lattice over lava
+
Floors no longer get dirty by walking on them
+
Zone selection tweaked; shouldn't notice anything different
+
melting research lockboxes no longer dumps the contents
+
Fixes reflective blobs using horrifying code that didn't reflect things *properly*
+
Fixes APCs not being hackable
+
Fixes explosions not properly interacting with storage items
+
+
Ionward updated:
+
+
Fixed a single pixel offset on Grey's Bags of Holding sprite.
+
+
JKnutson101 updated:
+
+
Shades can be stored in any Soul Stone.
+
Shades can once again be stored in Soul Stones.
+
Non-cultists and Non-wizards can no longer use most Soul Stones.
+
Cult Specters properly log as antags.
+
Cult Specters are properly removed from the cult on death.
+
+
KasparoVy updated:
+
+
Fixes an issue with the Tajaran striped tail's wagging animation by removing an extra frame.
+
+
PidgeyThePirate updated:
+
+
The abductor's silencer now actually silences radios for 10-20 seconds.
+
+
SteelSlayer and McRamon updated:
+
+
Added a new subtype of shade used exclusively by cultists to prevent chaplains metagaming with their shade sprites
+
Renamed path names for the altar and archives to be less confusing, and replaced all instances of the path names to reflect the change
+
Replaced nearly every sprite for reaper cult, including constructs, structures, airlocks and the reaper himself.
+
Removed the old reaper cult construct sprites
+
+
craftxbox updated:
+
+
cult teleport rune teleporting ai eye
+
+
+
07 October 2019
+
AffectedArc07 updated:
+
+
SQL now properly disconnects at end round
+
+
Couls updated:
+
+
reviver implant now heals even when you're conscious
+
+
Darkmight9 updated:
+
+
Hair styles, body markings, clothes, and other character customization options are now alphabetized.
+
+
Fox McCloud updated:
+
+
Most things are universally damageable
+
Acid melts things a bit differently now
+
Lava actually sets most things on fire.
+
Captain no longer has access to his display case by default
+
Xenos can break open vents
+
Fix syringe in-hand icon not updating
+
Fixes syringes not having materials
+
Lethal injection syringes should be a bit more...lethal
+
PDA health scans should be more in line with regular health analyzer scans
+
some blood type fixes, nothing noteworthy
+
+
Ionward updated:
+
+
fixed invisible Drask surgical masks
+
added Drask surgery cap icons
+
+
JKnutson101 updated:
+
+
Pylons heal robotic limbs.
+
Soul Shards fail when used on mobs that have never had a ckey.
+
Soul Stone Shards properly poll dead chat to be filled.
+
Incorrect icon path for reaper tome
+
+
Kyep updated:
+
+
Fixed the medkit spawning in the syndie depot being empty.
+
+
PidgeyThePirate updated:
+
+
Revived simple animals keep their ability to pull things and their density if they originally had it.
+
replaced the Lavaland winter dome ATV with a snowmobile.
+
The snowmobile key in the winterdome now accompanies an actual snowmobile instead of an incompatible vehicle.
+
+
SteelSlayer updated:
+
+
Added GPS coordinates under that status tab for cyborgs which have a GPS
+
You can no longer fire mining cyborg's KA with no cooldown
+
Bought items from the wizard spell book are first placed into any empty hands. If all hands are full, it places the item on the ground.
+
Cultists no longer get more than one summon objective
+
Mindslaves now show up in their own "Mindslaves" section in the check antagonists panel
+
Mindslaves will now get their objectives added to their notes and announced in their chat properly
+
Mindslaves will now have the red (A) in admin attack logs, which shows that the attacker is an antag
+
+
TDSSS updated:
+
+
fixed visual issues in beach gateway
+
+
farie82 updated:
+
+
Tickets can now be unassigned by staff members.
+
Toxic compensation now deals the right amount of toxic damage. Instead of just the last healed damage
+
+
+
30 September 2019
+
Couls updated:
+
+
Renames slime organs to be more player friendly
+
+
PidgeyThePirate updated:
+
+
The Ripley now collects all the ore it unearths after drilling.
+
+
SteelSlayer updated:
+
+
Cultists will no longer get multiple summoning objectives
+
+
TheSardele updated:
+
+
MULEbots no longer cause any damage when running over SSDs.
+
+
Ty-Omaha updated:
+
+
"Factual" changed to Actual in the explosion doppler array detector system
+
+
+
29 September 2019
+
AzuleUtama updated:
+
+
The camera bug now lists all cameras in alphabetical order.
+
+
Couls updated:
+
+
species without bones no longer have ribs or a skull either
+
slime heart and fleshy masses no longer go invisible after being removed through surgery or being eaten or necrotizing
+
+
Evankhell561 updated:
+
+
replace high power cells with high power cell+
+
+
Fox McCloud updated:
+
+
can insert keys into vehicles instead of having to hold them in your hand (alt-click while riding a vehicle to remove the key); lava boat still requires holding the key in your hand
+
Fixes moving diagonally with vehicles making you super fast
+
Vehicles now factor in the configured human movement delay; this means all vehicles are slower than they previously were
+
fixes a bug with mobs on vehicles causing incorrect space transitions
+
ATV sprites updated
+
Slime speed potions can now apply to vehicles, which makes them faster
+
+
JKnutson101 updated:
+
+
Allows for robotic hands, feet, and groin to undergo customization surgery.
+
+
PidgeyThePirate updated:
+
+
Abductor surgery will now remove heart subtypes.
+
Capitalized abductor surgery names for consistency with the surgery UI.
+
changelings no longer go bald after reviving.
+
+
+
27 September 2019
+
PidgeyThePirate updated:
+
+
Rebooting a drone no longer requires both engineering and robotics access.
+
fixed a rare glitch in which a guardian that is killed instantly (i.e by a wand of death) may draw its charge into null space.
+
bluespace anomalies no longer teleport ghosts when their event fires.
+
+
SteelSlayer updated:
+
+
Fixes round-start autotraitors not getting their objectives and uplink codes
+
+
+
26 September 2019
+
AzuleUtama updated:
+
+
Improvised shotguns are now in the correct tab when trying to craft them.
+
+
Couls updated:
+
+
Slime lungs and heart
+
Slimes no longer take toxins damage from blood loss
+
Slimes no longer take brute damage in crit
+
Slimes now breathe
+
slimes now use new crit
+
+
Kyep updated:
+
+
Fixed NPC redsuited syndicates from being unable to move in space.
+
Fixed NPC bots thinking that they can path through airlocks which are welded shut. refactor: Refactors some safety checks so that its impossible for depot mobs to generate runtimes in rare cases (e.g: admins spawning them outside the depot for testing)
+
+
MrMagolor updated:
+
+
Cult pylons no longer delete unsimulated walls and turn them into floors.
+
Cult pylons now turn simulated walls into cult walls.
+
+
TDSSS updated:
+
+
added missing tools to one abductor ship
+
+
farie82 updated:
+
+
Morphs examine text now stays true to the humanoid target they choose.
+
Cult constructs now show their examine text when you're next to it. Instead of on top of it.
+
+
+
24 September 2019
+
AzuleUtama updated:
+
+
Fixed misleading uplink description for chef's traitor knife.
+
Reorganises products in seed vendor.
+
Fixes Durathread mutating into more Durathread
+
+
Dave-TH updated:
+
+
Mob spawners will no longer sometimes send players to the void.
+
The ghosts inside possessed blades are now invincible and will not die to weird edge cases.
+
+
Evankhell561 updated:
+
+
mechs now start with a high-capacity power cell+
+
+
Fox McCloud updated:
+
+
Buckling has its own icon
+
Fixes Xenobio monkey shortcuts not working
+
Bodyscanners are similar to sleepers; interact with them by clicking on the scanner; there is no console anymore
+
Summon guns/magic is no longer free, but costs 2 spells points
+
Summon guns/magic makes 10% of the crew antags with the objective to collect guns/magical items and kill anyone who gets in their way
+
If a wizard (or admin) summons guns/magic, latejoiners to the round will also acquire summoned items
+
Wizard's hardsuit is now battlemage armor
+
Battlemage armor protects you from pressure of space (but not the cold), has no slowdown, and a moderate amount of armor, however, it has 16 shields to block incoming attacks
+
Can purchase additional charges for your battlemage armor for 1 spell point
+
Shielded hardsuits now show the shield on the mob
+
Abductors, Skeletons, Shadowlings, and Plasmamen never get hungry
+
Abductors, Skeleton, and Plasmamen can't taste anything
+
Wood Golems now have a diet and taste sensitivity much like Diona
+
Unathi are more sensitive to tastes
+
Adjusted the sensitivity of "sharp" and "dull" tastes a bit
+
Slimes are a simple mob subtype
+
using a bloodlust slime potion on a docile slime removes the docility
+
using a docility potion on a rabid slime calms them down
+
slime core removal surgery steps are now just scalpel->hemostat
+
Slimes have action buttons to feed on, evolve, or reproduce
+
Fixes beepsky arresting slimes (maybe it should be a feature....)
+
Fixes Seed Vault gene modder having limitations
+
Fixes not being able to extinguish some items
+
+
Ionward updated:
+
+
Fixed Tajaran fat sprites, they are no longer duplicates of their slim torso.
+
Fixed fat aqua jumpsuit only using one direction.
+
Fixed missing Lasagna icon.
+
+
Kyep updated:
+
+
The Hierophant club and warp cubes (lavaland loot) no longer allow you to teleport into or out of areas that are set to forbid teleports.
+
Fixed a small bug that caused coins named "syndicate coin" or "antag token" to both incorrectly appear as "valid coin".
+
+
Markolie updated:
+
+
Fixed naked equipment selection and reincarnation not working.
+
+
TDSSS updated:
+
+
all huds are the first option when ghosts cycle through huds
+
fixed brig door timers from announcing admin names when stopped via admin powers.
+
+
Ty-Omaha updated:
+
+
You can now silence the current midi with a verb in the preferences tab, without affecting your prefrence to hear midis in the future.
+
+
datlo updated:
+
+
Fixed clown changelings not losing comic sans on transformation
+
Clowns can now lose the clumsy and comic genes through DNA manipulation (but not mutadone)
+
+
+
22 September 2019
+
Evankhell561 updated:
+
+
Mech ID upload panels now come with [add all] and [delete all] options
+
+
Fox McCloud updated:
+
+
Fixes corpses/lying down mobs blocking projectiles
+
+
MarsM0nd updated:
+
+
can safely pick up nettles again
+
+
SteelSlayer updated:
+
+
Traitor and mindslave status is handled in a datum instead of the mind
+
You can no longer use a mindslave implant on a person with no mind
+
Adds the ability for admins to de-mindslave somone through the traitor panel
+
De-traitoring malf AIs via the traitor panel removes all instances of their Law 0
+
De-traitoring malf AIs via the traitor panel removes their ability to still state laws over the syndicate channel
+
De-traitoring malf AIs via the traitor panel removes their ability to shunt to hacked APCs
+
Unemagging borgs via the traitor panel properly removes their syndicate laws and gives them the crewsimov lawset
+
Unemagging borgs via the traitor panel who did not have a module selected does not cause a runtime anymore
+
+
TDSSS updated:
+
+
Just slight gloves refactor, shouldn't impact anything in game.
+
+
+
21 September 2019
+
AzuleUtama updated:
+
+
The Captain's rapier can now be assigned as a theft objective.
+
Slime extracts and plasma tanks have been removed as theft objectives.
+
Document trading no longer counts towards a traitor's total number of assigned objectives.
+
Fixes a grammar error with the ambulance and slightly misleading description with the combat gloves.
+
Headpat gloves now inherit their click speed from the North Star gloves and are no longer as fast as before.
+
Sarin gas grenades no longer purchasable for nuke ops. balance: Grenadier belt now contains a sarin gas grenade. balance: Tactical medkit's hypospray tweaked to contain chems better for dealing with newcrit. balance: C20 bundle increased in price to 18TC, contains an additional clip of ammo. balance: Medical bundle increased in price to 20TC, Donk LMG removed, replaced with medbeam gun and magboots.
+
Fixed some minor spelling/grammar errors with synthflesh patches and sarin gas grenades.
+
R&D Console no longer has a default design called 'Name' show up in the mining category.
+
Syndie and Binary keys now use their own sprites rather than the default ones.
+
+
Couls updated:
+
+
Romerol virus that requires two traitors to team up to purchase
+
zombies that have a slow but steady health regeneration and cannot be killed permanently outside of decapitations and removal of the tumor in the brain
+
blood no longer stacks on itself endlessly
+
fixes footprints stacking
+
removes zombie from the secondary language list
+
hotkey menu option in the dropdown works correctly now
+
configurable limit to amount of monkeys that can be spawned by monkey cubes
+
handle_death is passed the gibbed variable
+
spec_death replaced with handle_death in romerol
+
you no longer hit yourself with things you throw
+
missing arguments in some procs
+
some macros that were defined twice
+
recycled monkeys were not being subtracted from the monkey cap
+
+
Dave-TH updated:
+
+
Fixes some vending machines (namely miner nanomeds) from adding all of their product twice.
+
Magical weapons can now be properly dual-wielded.
+
Fixes the description of energy shields, which said they block things that they do not.
+
Crayon drawings can stack again.
+
Crayons can no longer draw on multiple tiles at the same time, sorry octo-artist!
+
Fixes the lack of cooldown on attacking light fixtures.
+
Examining an air analyzer now informs you about its lesser-known function!
+
+
Emanthealmighty updated:
+
+
Updated the netherworld creatures' sprites.
+
+
Fox McCloud updated:
+
+
refactored gloves of the North Star to be more adminbusy
+
Adds Gloves of Headpats to the pet vendor as a premium item
+
Refactors the very core and soul of SS13 and enhances the code that powers it
+
Bible fartgibbing is now a form of suicide
+
Fixes mice coming back to life
+
Fixes nurse spiders not wrapping things
+
Fixes spiders not spazzing out
+
Simple mobs will now attack everything in the vicinity instead of just specific object types
+
Gutlunches now eat internal organs
+
ranged guardians don't rapid fire anymore, but have a lower cooldown on attacks
+
Fixes some turf underlays not working
+
adds in a wooden hatechet and rake to the ashwalker base; replaces the regular bucket with a wooden one
+
Fixes some blank tastes
+
Fixes not being able to brew fruit wine
+
Fixes poor TG copy pasta code that caused hundreds of runtimes
+
Reduces round-start lag
+
Fixes certain PDA cartridges causing insane performance loss
+
Carp Migration event no longer deletes the carp when it ends; they will continue to stick around the station
+
Personal crafting now has subcategories
+
Finishing crafting an item puts it in your hands instead of on the floor
+
comments out romerol (much like zombies, it will rise again, don't worry!)
+
zombies are high and lower pressure immune in addition to immune to heat and tox damage
+
Ian now has persistence; if he's killed, he'll start over life as a puppy--if he lives to a very long old age, he'll get a unique sprite
+
Pugs will now yipe on death and can bark
+
Adds new dog mob; a generic black dog
+
Foxes are now a dog subtype
+
Can manually yelp as a dog
+
All dog subtypes can now chase their tail and be given pats and pets. They all can additionally eat (and taste!) food
+
Nar-Sie will absolutely not tolerate sacrificing doggos
+
Ripleys are slightly faster on station, but dramatically faster on Lavaland
+
Mech mining drings can no longer drill through floors; they also don't just drill once. After a short delay, they'll attempt to drill the target, repeatedly.
+
Mech mining drills no longer instantly knock out mobs; if the mob is dead and has over 200 brute, the drill will attempt to harvest or gib the mob; can also disembowel
+
Mech plasma gun has a lower cooldown
+
Mining scanners apply a much brighter and visible overlay; mining a turf will now instantly clear the overlay
+
Mining mech (the one that's a lavaland find) has a partially depleted cell; it'll also no longer have multiple mining tools on it
+
Fixes null animal type with regards to pugs
+
Legion body loot adjusted; may find rare alternative mining belt or primitive one; bone bracers also show up on Ashwalkers; mini pickaxe spawn also possible
+
Large legions can damage objects
+
Small legion skulls no longer block mob movement
+
Basilisks are now gold core spawnable
+
Gutlunches no longer produce adult version of themselves, but have babies that grow into gutlunches
+
Mining belts can now hold pillbottles and shovels
+
Goliath cloaks hold different items now; more inclined to what Ashwalkers would use and not miners
+
Swarmer megafauna now has its proper GPS
+
Can't kill mining fauna by overheating them
+
new sprite for the Hierophant
+
Refactored tendrils; they won't show up on health HUDs anymore
+
Fixes Tendrils not emitting light
+
Fixes tendrils not changing the terrain around them
+
Fixes being able to exploit vending machines by deconstructing then reconstructing them to get additional items. Get an additional restocking units from cargo you filthy dirty exploiters
+
All vending machines require only a single restocking unit to build
+
Clothing, NanoMed, Wallmed, Vendomat, EngiVend, NutriMax, Megaseed Servitor, Sustenance Vendor, Dinnerware Vendor, Cart Tech, Robco Toolmaker, soviet BODA, security tech, and modular PC vendors are all now makeable/restockable
+
Most vendors can be damaged by brute force (Nanomed, wallmed, and youtool are notable exceptions)
+
Most restocking units can be ordered from cargo
+
Removed snowflakey laptop vendor
+
Adds in new laptop+tablet vendor; don't expect it to have as much (ask science for upgrade parts!)
+
Sustenance vendor has a new set of contraband if prisoners can actually hack the thing
+
breaks up the clothing restocking unit cargo pack from a single pack into 4 separate packs, 15 points each
+
Fixes Megafauna spawning near the base
+
Fixes lava rivers not forming
+
Upped the labor mineral spawn rate
+
Removed the ability to find random code-locked crates when mining
+
Watcher Icewing blasts will briefly freeze you
+
Fixes too much detecting corgis
+
Tweaks a few reagents tastes
+
fixes being able to taste metaphorical salt
+
nutriment no longer restores blood
+
Nuke ops can no longer advanced syndie magboots
+
Fixes an inconsistency with chameleon kit pricing--it was only 2 TC, making the no slip syndicate shoes worthless; price is now 4 TC
+
operatives pay 2 TC more for the no slip syndicate shoes and the chameleon kit
+
Wizard hardsuits no longer come with magboots
+
Syndie magboots are nuke ops only
+
Can purchase no slip shoes from the uplink instead of a full chameleon kit
+
Operatives can purchase no slip syndicate shoes
+
No slip shoes can protect against atmos pushing
+
removed most round-start magboots with the exception of EVA, atmostechs, CE, and engineering hardsuit dispensers
+
Fixes carp not being a threat to the station due to killing themselves
+
Fixes being able to exploit simple mob AI so it kills itself in an atmos death blender
+
vent and scrubbers work far more efficiently and quickly now
+
Fixes wideband on scrubbers constantly resetting itself
+
Portable scrubbers far more effective
+
Flamethrowers far more effective
+
Nanofrost twice as expensive
+
regular syndicate borgs don't have magpulse by default
+
Atmos pushing completely refactored; it'll still push you frequently and push items around frequently, but it won't throw you. Depending on how many dense objects or turfs are around you to "grab onto" will determine how effective atmos is at pushing you around. Does not alter the speed at which LINDA runs.
+
Plasma glass shards do less damage when attacking, but slightly more when stepping on them
+
Spears made out of plasma glass do slightly more damage
+
Light replacer can now be used in-hand to attempt to reload empty lighting fixtures around you in addition to showing how many lights it has
+
Light replacer needs less shards to increment bulbs
+
Updates moonflower, sunflower, novaflower, and pineapple sprites
+
Adds in Garlic
+
Fixes a few issues with incorrect values from the wine PR
+
Can now grow and extract the reagents/traits of Lavaland flora
+
Slightly tweaks soybean oil production on soybeans
+
Adds amusing garlic suicide
+
Ash Drake reworked; it's much more powerful now and has a diverse set of attacks--its fire breath is more random, it moves faster, it can turn the ground into lava, and once it's lower on health, will seal you into an arena and make you play the "only one turf is safe; stand on it or suffer" mini-game
+
Bubblegum is now much more difficult; instead of just spraying blood at you and attempting to endlessly charge you (walking backwards essentially counters it), it's now faster, engages in zig-zag attacks, uses a hallucination multi-attack, and can rapidly melee attack you in range
+
Fixes megafauana endlessly attacking dead mobs
+
Blood drunk Colossus, and Ash Drake made to be more player friendly if they control the fauna
+
Adds in Space dragon; a very weak version of the Ash drake which can't swoop, but can still breathe fire--has a spell that whips you back with its tail, too (not currently used anywhere)
+
The real Roman shield and real Roman helmets in the Autodrobe have been replaced by fake, armorless, varieties
+
Hierophant has been updated--it'll be a bit tougher and will attempt to trap you if you run for it.
+
Heirophant is no longer a weird bird thing, but a massive, indecipherable piece of machinery that will make you dance to ITS tune
+
Hierophant club is weaker up front, but becomes stronger the lower health you are
+
Fixes tendrils spawning inside ruins
+
Fixes light replacers breaking/hitting lights
+
Fixes blood drunk buff not making you slow immune
+
Regenerative core will give you 1 minute of slow immunity on application
+
carp sprites now support a wider range of colors
+
Megacarp names randomized in addition to their stats
+
Adds new friendly life reaction (strange reagent + synthflesh + sugar + heat)
+
Life reaction amount of critters spawned varies with created volume
+
Can now spawn the xeno maid, lightgeists, and bees with slimes cores/life
+
can no longer spawn the Shamebrero penguin with slimes cores/life
+
Adds new EVIL crab; is a "hostile" slime core/life mob
+
simple Xenos are a bit more powerful
+
Butchering simple Xenos now leaves a Xeno hide; use it to make a Xeno costume
+
Fixes spriteless dog
+
Fixes being able to spawn Proc with slimes cores/life
+
Fixes Blooddrunk being a flying mob
+
can move dense objects around corners
+
Removes unused, highly buggy VR code
+
Completely transitions to Lavaland for all maps. The mining asteroid and it's related bits are removed
+
Vox reworked
+
Vox are no longer spaceproof
+
EMP's no longer wreck cortical stacks
+
Vox cortical stacks are their brains; there's no longer two separate organs for Vox brain+cortical stack
+
Vox are immune to decay and will not skeletonize
+
Vox internal organs will never accumulate germs or decay, even when they're outside a Vox's body
+
Vox external organs do not accumulate germs when attached to their body
+
Vox have silent footsteps
+
Vox can process BOTH organic and synthetic reagents
+
Diona no longer decay into skeletons
+
Can now pick the species you want to play as for lavaland ghost roles
+
Golems have been buffed.
+
Golems are faster, better protected against damage, and have limbs that cannot break or be dismembered.
+
Golems are no longer virus immune
+
Golems can now wear labcoats and boxing gloves
+
Fixes golems being able to be healed/injected on parts other than the chest
+
Having a robotic chest allow you to wear an ID, PDA, and belt without a jumpsuit. Having a robotic right leg allows you to use your right pocket without a jumpsuit; same for your left
+
stepping on glass tubes now shatters them; can trip you up if you aren't wearing shoes
+
Stepping on a D4 will deal between 1 and 4 damage to you if you aren't wearing shoes and trip you up
+
skeletons have built in pierce immunity
+
+
Ionward updated:
+
+
Greys, Unathi, Tajaran, and Vulpkanin now have sprites for Lavaland reward hardsuits (Wizard, Elite Syndicate, and Paranormals), Biosuits, Voidsuits, and Syndicate Soft suits.
+
Plasmamen Librarians now have visible helmets.
+
Atmos Hardsuits now have inhand sprites again.
+
Added new uniform and hat to the AutoDrobe, the Rhumba outfit.
+
+
KasparoVy updated:
+
+
Tajaran characters can now have the tiny & short tails (plus marking).
+
Adds a striped tail marking for Tajara derived from the sriped/wingler body accessory to allow more flexible colouration.
+
Renames Vulpkanin alt. tails for brevity and easier keyboard navigation.
+
+
Kyep updated:
+
+
Fixed bug that made the syndicate depot impossibly difficult.
+
Various improvements to syndi depot, such as use of plastitanium walls, and nerfs to some cheese strategies.
+
Ported TG's simple_human.dmi, a sprite file of humanoid sprites (including syndicates).
+
Added a few extra syndi sprites from FoS.
+
fixed an issue with keyboard input
+
Brig timers now display the job of brigged people. E.g. "Joe Schmoe (Chemist) was incarcerated" as opposed to just "Joe Schmoe was incarcerated".
+
Brig timers now notify a person's boss via PDA when they are incarcerated. E.g. if a chemist is temporarily brigged, the CMO is notified of the brigging via PDA.
+
+
Markolie updated:
+
+
Guardian communciation now longer shows up to players in the lobby.
+
+
Mocha-Not-Latte updated:
+
+
Fixes #12354
+
+
Shadow-Quill updated:
+
+
Fixed ATM withdrawals doubling.
+
Fixed Fore Port Solars' APC not charging.
+
Fixed a typo in admin gloves of rapidness.
+
Plasma cutters will no longer eat plasma if you try recharging a full gun.
+
Blobs now get a audio notification roundstart (like traitors do.)
+
+
SomeSortaSquid updated:
+
+
Karma purchases no longer loop infinitely, leading to repeated purchase prompts or "You do not have enough karma!" message after successful purchase.
+
+
SteelSlayer updated:
+
+
The AI and magistrate get bold text when the "louder command members" telecomms setting is on
+
Command members will get the first letter of their radio message auto capitalized when the "louder command members" telecomms setting is on
+
Malf AI's overload machine & override machine action button behavior is changed to a point and click style ability.
+
Added some new mouse pointer icons for the machine overload and machine override abilities
+
The "Show Player Panel" verb is now right click only
+
The "C.M.A. - Admin" verb is now right click only
+
The "C.M.A. - Self" verb is now right click only
+
The "Check Contents" verb is now right click only
+
The "Freeze" verb is now right click only
+
The "Freeze Mech" verb is now right click only
+
The "Jump to Turf" verb is now right click only
+
The "Update Mob Sprite" verb is now right click only
+
The "List SSDs" and "List AFKs" verbs have been combined into one verb named "List SSDs and AFKs"
+
The "Resolve All Open Mentor Tickets" verb has been moved inside the mentor ticket interface window
+
The "Resolve All Open Admin Tickets" verb has been moved inside the admin ticket interface window
+
Increases the width of the new "List SSDs and AFKs" window a bit
+
The gravitational catapult no longer pushes ghosts when used
+
Fixes a runtime preventing walls from being repaired properly
+
Adds the ability to repair and remove bullet holes from reinforced walls that have no structural damage
+
+
TDSSS updated:
+
+
local gps signals, visible only on the same z level
+
lavaland mob signals were made local, reducing gps clutter
+
Objective to abductors to not disrupt crew too much.
+
healing fountain lavaland ruin now correctly heals
+
lowered attack log level of self-harm
+
certain harmless chems and food have reduced attack log logging levels
+
the most grave of wrong tips
+
The uplink dart gun now comes with some syringes to use with it.
+
+
Terilia updated:
+
+
stat_attack from unconscious to dead
+
added new headcrabs (poison and fast)
+
added new headcrab sounds for the poison headcrab and the fast zombie
+
+
TheMadTrickster updated:
+
+
fixed wonky/bugged sprites for custom guitar and hair gel
+
new improved clean sprites for custom items
+
old messy sprites for custom items
+
+
TheSardele updated:
+
+
Changes the attack log setting required to have the blood-drunk miner buff actively log to all attack logs.
+
+
Ty-Omaha updated:
+
+
Headpat gloves added to arcade machine prizes
+
Minor ban evasion update
+
Autonote for manual bans removed
+
SSD players no longer drown in shallow water
+
Admins can now autoreply with common answers to common questions / issues.
+
Opening an adminhelp/mentorhelp ticket will play a sound
+
Adminhelp ticket information color changed from neon green to a more toned down green
+
Global admin midis will now silence lobby music for those who have midis enabled.
+
Adds "Man Up" to autoreply
+
Autoreponses now show up as the last admin response in tickets
+
Fixes an issue where autoresolve was appearing in mentorhelps to mentors
+
Resolve button on adminhelps and mentorhelps work again
+
Fixes reversed logic in autorespond confirmation alert
+
Removed custom admin event info that only admins could view due to confusion with the regular non-admin verb.
+
+
datlo updated:
+
+
Added the Banana Touch and Mime Malaise spells to the Wizard spellbook.
+
Station goal crates now come in engineering crates.
+
Replaced the red emergency toolbox in hermit ruin by a regular blue toolbox.
+
+
farie82 updated:
+
+
Hoodies now work like they do in TG. Less abuse of NO DROP, more better
+
Welding a tile away now gives a more useful message when doing so.
+
Admins now don't get spammed by hugs.
+
+
kazboo updated:
+
+
added a nice metalic alarm sound for when the nuclear self-destruct is activated on the station.
+
candle boxes on the station are now properly filled
+
+
variableundefined updated:
+
+
Multiple food now have their own tastes
+
Corgi and mice can now taste food
+
Hallucination causes you to taste strange things
+
Nutriments now carry over the tastes of food
+
A quick resolve button to adminhelp and mentorhelp message!
+
Config option to let gamemode ignore the number of required players.
+
Hit_reaction proc has been refactored.
+
Flamethrower and grenade detonation by shot is now logged.
+
Refactored wooden chair so placing them won't make you see normal metallic chair anymore.
+
Contribution guideline has been updated. No in game changes.
+
Github pull request template has been changed
+
Officer starter pack to cargo. For 30 cargo points you can equip an officer just like an officer closet! Backpack not included due to budget cut.
+
+
xProlithium updated:
+
+
Replaced link to CA (check antags) in adminhelps, tickets, and adminmoreinfo with a link to TP (traitor panel)
+
Altered CA to TP for prayers and adminpms.
+
+
+
30 August 2019
+
AffectedArc07 updated:
+
+
Fixes the changelog
+
+
Arkatos updated:
+
+
Added new icon for Charge spell
+
Added new icon for No Clothes spell
+
Added new icon for Wizard spellbook
+
Added new animations to 10 single-use spellbooks
+
Added new sprite for Bottle of Tickles
+
Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
+
Fixed an issue where Bottle of Tickles did not properly refund
+
Fixed an issue with alpha layering on Bottle of Ooze sprite
+
Very slightly adjusted brightness of the Boo! ghost spell icon
+
Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
+
Polymorph can now turn a mob into Syndicate medical or saboteur modules
+
Mobs made via polymorph into borgs are now unbounded free borgs
+
Repulse spell cost decreased from 2 to 1
+
Lighting bolt spell cost decreased from 2 to 1
+
Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
+
Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
+
Improved descriptions and wording regarding Wizard spellbook and Wizard spells
+
Traitor AI now uses action buttons for its malfunction abilities
+
+
AzuleUtama updated:
+
+
Adds false-bottomed briefcase from VG.
+
+
Couls updated:
+
+
Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
+
Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
+
DUAL WIELDING
+
new chatsubsystem from TG!
+
Update issue templates to latest version and clean up the current template
+
mining shuttle warning message and delay before launching
+
cardboard boxes are no longer sonic speed
+
shuttle timers now get set properly
+
+
EmanTheAlmighty updated:
+
+
Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
+
Blobbernauts and blobs can now communicate with each other.
+
Blobbernauts now regenerate health overtime when standing on blob structures.
+
Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
+
+
Emanthealmighty updated:
+
+
The poll to play as a blobbernaut now lasts 10 seconds from 15.
+
Blobbernauts no longer chase after people while players are being polled to play as one.
+
+
Fox McCloud updated:
+
+
Plasmamen dramatically overhauled.
+
Plasmamen can be cloned without burning to death in the clonepod
+
Plasmamen no longer start with spacesuits
+
Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
+
Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
+
Plasmamen take 50% extra brute and burn
+
Plasmamen are immune to radiation
+
Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
+
Plasmaman helmets now have built in welding goggles
+
Plasmaman karma cost lowered from 100 to 45
+
Reworks Diona
+
Diona bleed (call it chlorophy; it's green)
+
Diona Breathe (plants do need to exchange gas after all)
+
Rad Immunity Removed
+
Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
+
Diona no longer have unbreakable bones (wood can crack ya know!)
+
Diona are no longer space proof
+
Diona are more vulnerable to fire and heat damage
+
Diona weakness to weedkiller dramatically nerfed
+
Diona now use Newcrit
+
Diona are no longer slow
+
Diona can wear spacesuits
+
Fixes stun absorbing not working
+
Fixes parallax insane setting not doing anything
+
Ores can be destroyed by devastating explosions
+
silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
+
drills slightly slower, but diamond drills slightly faster
+
Spade is the same speed as a shovel
+
Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
+
can use a hivelord core in your active hand to apply it to yourself
+
soulstone in the abandoned locked crates can now be used by anyone
+
Adds firelemon seeds to the abandoned locked crates as potential loot
+
Hardsuits have an integrated helmet; you no longer have to attach helmets
+
Toggling up/down helmets is now done with an action button
+
can no longer attach magboots to a hardsuit
+
Hardsuit base melee armor increased from 10 to 30
+
Security and HoS hardsuit melee armor increased by 5
+
HoS hardsuit helmet armor matches his hardsuit
+
CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
+
Elite syndicate suits can't be acided
+
Fixes stuns and weakens related to reagents
+
Fixes the displayed cost of Plasmamen
+
Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
+
Removes mining carbon dioxide jetpack
+
Can no longer use jetpacks in your suit storage slot
+
Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
+
Fixes random singularity releases from the grid check event
+
loadout costs for most things cut from 2 to 1
+
Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
+
moved hipster glasses from donator to general glasses
+
Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
+
Removes access based security barriers
+
Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
+
can tear up bedsheet and gauze to get cloth--requires a sharp object
+
Fixes plasmamen atmos techs not getting their proper suit
+
Adds in a loom, craft one out of 10 wood
+
Adds in cotton and durathread cotton to botany to grow
+
Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
+
Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
+
Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
+
Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
+
adds a whole range of beanies, find them in the clothing vendor or make them yourself
+
Updates the cowboy boots sprites
+
Unironically fixes about several thousand runtimes
+
Fixes jackets not keeping you warm
+
Chefs are now trained in the art of Close Quarters Cooking
+
Adds the Book of Babel as tendril loot
+
Adds Jacbo's Ladder as tendril loot
+
Fixes fungus, blood, and graffiti not showing up on a wall
+
Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
+
Fixes baseball bats throwing anchored things
+
Fixes blood drunk buff
+
Fixes using a crusher on a trophy to equip it causing you to drop the crusher
+
refactors lazarus capsules; no real behavioral change
+
Fixes being able to revive megafauna with strange reagent
+
+
Fox McCloud and FullOfSkittles updated:
+
+
Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
+
Fixes telebacon not properly acting as...well, a bacon beacon
+
+
FreeStylaLT updated:
+
+
Added an Engine Picker, which uses new engine beacons.
+
Replaced the current two engine generators with one engine beacon.
+
+
Ionward updated:
+
+
Drask crewmembers now have properly fitting shoes.
+
Fixed some minor issues in Drasks uniforms
+
non-humans now have proper sprites for durathread goods
+
+
KasparoVy updated:
+
+
Adds sprites for all Vox & Armalis earwear.
+
Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
+
You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
+
Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
+
Fixes an issue preventing the species-fitting of earwear.
+
Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
+
Picking up uniforms no longer renders a default grey jumpsuit on Vox.
+
Resolves an issue causing shining eyes to be rendered darker than intended.
+
Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
+
Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
+
Non-shining eyes render the proper colour again.
+
+
Kurgis updated:
+
+
Beepsky now bumps around on its wheels when patrolling for crime.
+
+
Markolie updated:
+
+
A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
+
Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
+
The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
+
A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
+
Outfits now support accessories and internal boxes.
+
The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
+
Water coming from sinks and certain water effects is now 10C instead of body temperature.
+
+
Shadow-Quill updated:
+
+
[Meta] Added buckshot and slugs to armoury.
+
[Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
+
[Meta] R&D doors now has proper access requirements.
+
[Meta] Added RCS and telepad to cargo.
+
[Meta] Disposals sheet stacker and conveyor belts now works properly.
+
[Meta] One-way airlocks added in Medbay/Brig.
+
[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
+
AIs not being able to restore their own power if in an area with an APC.
+
Fixed being able to talk in OOC under certain circumstances if it's disabled.
+
Lockers can no longer move around anchored mobs.
+
+
SteelSlayer updated:
+
+
You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
+
The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
+
A cable adding sound gets played when you add wires to create a terminal for a SMES
+
Rapid pipe dispensers can now place disposal sorting pipes
+
When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
+
Added a destination tagger to the atmosheric technician locker
+
Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
+
Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
+
IV bags are able to transfer their contents to other containers by clicking on them with the bag
+
Adds a handheld defibrillator to the paramedic EVA closet
+
You can insert magazines into L6 SAWs again
+
Removed one of the high capacity tanks in hydroponics
+
Added a disk compartmentalizer to hydroponics
+
Delaying round start actually delays round start again
+
+
Terilia updated:
+
+
added headcrabs
+
adjusted the path's for headslugs. They are not called headcrab anymore
+
+
TheSardele updated:
+
+
Removes the ability of obese people and those with matter eater to swallow others.
+
+
Ty-Omaha updated:
+
+
Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
+
+
datlo updated:
+
+
Added ashstorm immunity to titanium and plastitanium golems.
+
Added lava immunity to plastitanium golems.
+
Bananium golems now slowly waddle around.
+
Uranium golems now properly irradiate nearby mobs that arent rad immune.
+
Tranquillite golems now properly get their miming powers.
+
Added the Clown and Winter biodomes as possible lavaland ruins.
+
Update a changeling error message to be clearer.
+
+
farie82 updated:
+
+
Items with NODROP that are dropped now lose the flag if they didn't get created with it
+
Adds tip text to the examine text of the ambulance trolley about how to attach it
+
Adds tip text to the nuke when trying to use the NAD before deploying it
+
Adds tip text to the fire axe cabinet about how to lock/unlock it
+
Adds tip text to airlocks if they have a note on them about how to remove the note
+
Can't put the NAD in the nuke now when it has the NODROP flag
+
Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
+
Can't put a nodrop fire axe in fire axe cabinets now. Duping them
+
Implants like the IPC charging work again. They won't get deleted after first use
+
+
variableundefined updated:
+
+
A proc's name got changed. That's it
+
+
+
23 August 2019
+
AffectedArc07, Keekenox, Floyd/Qustinnus updated:
+
+
P A R A L L A X (That fancy space thing)
+
Adds a new Parallax layer that resembles Lavaland (Lava Planet), it spawns on a random location near the station. You need your parallax on high to see it.
+
+
Arkatos updated:
+
+
Added colored pillbottles
+
Added an option to change color of the pillbottles to ChemMaster3000
+
Added new description to patch packs
+
Jump to Node ability now shows a location of each Blob node
+
Added SlimeHUD when playing as a slime. This means slimes will have their own unique health doll and pull icon.
+
Action buttons can now be dragged onto each other to swap places
+
Fixed a case where dragging locked action buttons could result in white tooltip over the screen
+
+
AzuleUtama updated:
+
+
The Traitor thermal glasses and chameleon security HUD now use the updated chameleon code. balance: Traitor thermal glasses will no longer cause eye damage when hit with EMP.
+
+
Citinited updated:
+
+
Removes the big pipe dispensers from atmospherics, you can still find them elsewhere.
+
+
Couls updated:
+
+
After many complaints about being stuck in medbay. NT has modified all the airlocks on the station to allow leaving certain departments without requiring an respective ID. This new modification is indicated by a white light near the airlocks in the direction of unrestricted access.
+
New unrestricted access can be built by NT engineers through modification of the airlock electronics.
+
hit effects!
+
hit effect sprites for lasers, bullet hole and dent decals for walls
+
mice now have a very low chance of chewing through wires, this kills them if the wire is powered
+
You can now homerun things thrown at you with a baseball bat!
+
new baseball hit noise, new baseball sprite
+
there are much less one-way airlocks on station
+
+
DoctorDrugs updated:
+
+
removed the ability to eat the divine vocal cords
+
+
EmanTheAlmighty updated:
+
+
The AI can now change its intent by clicking on the new on-screen button or pressing 4 to switch to help or harm.
+
The AI can now toggle airlock safeties instead of toggling door bolt lights by pressing middle mouse.
+
+
Fox McCloud updated:
+
+
Majorly updates lavaland
+
Miner starting equipment altered. They now start with a kinetic accelerator
+
Miners start off with a mini pickaxe
+
Adds in the boxed implant kit, regular shelter capsule, and mining drone passthrough upgrade to the mining equipment vendor
+
re-ordered the equipment vendor, so things are grouped together more logically
+
Added a number of new kinetic accelerator upgrades acquirable through tendril chests
+
Mining bot now uses an actual kinetic accelerator as opposed to a "Look alike"; you can upgrade its internal gun with various kinetic accelerator modkits.
+
Sentient mining bot nerfed; you can no longer apply the armor or melee buff to them; offset by the fact you can upgrade their kinetic gun.
+
Indoor pressure mod removed from R&D and made into a miner traitor item
+
Resonators have an increased amount of fields and do more damage in low pressure. Additionally, if you place a field on a tile that already has a field, it'll cause it to detonate early
+
Plasmacutter no longer does increased damage in low pressure, Advanced plasma cutter does slightly more base damage but has a bit less range. Price has been cut at R&D
+
removed the AoE Mob+Turf upgrade for mining pods
+
Fixes ripleys being slow on lavaland
+
Fixes walking on lavaland sounding like walking on metal plating
+
Adds in kinetic crusher trophies
+
Kinetic crusher can be wielded/unwielded (but you can't attack with it unwielded)
+
Adds the HECK suit as Bubblegum loot
+
Adds the kinetic accelerator bounty mod as Tendril loot
+
Add fulton extract packs to the mining vendor; rescue precious valuable or dead miners!
+
Adds mini-fans to the mining, engineering, and security shuttles
+
Adds a number of primal recipes: rake (cultivator), wooden bucket, firebrand (long burning match), and bone bracers (armored arm protection that goes on your glove slot)
+
Can attach bayonets to C20rs, bolt action rifles, security auto-rifles, and kinetic accelerator; harm intent to stab with them
+
can craft ore boxes out of wood
+
Skull helmets are now proper helmets
+
Survival autoinjectors tweaked
+
Survival autoinjectors have 15 units of teporone in them
+
Survival autoinjectors have double the epinpehrine and weak omnizine instead of saline glucose.
+
lavaland extract altered; it no longer heals tox or oxy, and heals slightly less brute and burn, but has nearly halved the metabolization rate and has a less harsh overdose
+
Fixes airlocks spamming their open and close when you stand in them
+
Fixes overriden door timers not working
+
+
Fox McCloud and FullofSkittles updated:
+
+
Changes the Venus Human Flytrap sprite
+
+
Ionward updated:
+
+
Adjusted Greys uniforms and backpack sprites.
+
Added a bunch of Drask masks and glasses.
+
Added God Eye sprites for Greys, Drask, and Vox.
+
+
JKnutson101 updated:
+
+
Issue where Emergency NanoMed Vendors required Medical ID to Access.
+
Added the ability for cyborgs with zero battery to use the 'succumb' verb.
+
+
Markolie updated:
+
+
Players now have thirty seconds instead of just five seconds to select if they want to be somebody's butler through a die of fate roll.
+
The Netherworld portal is now properly destroyed upon being killed. In addition, its max health is now equal to its starting health.
+
The iron ore sprite that shows up when using the miner scanner no longer has a background, making it blend in better with the actual rock.
+
Tightening the bolts of a falsewall now works properly.
+
Deconstructing plating now requires it to be unfastened using a screwdriver first, in order to prevent it from being accidentally deconstructed with a welder.
+
+
Quantum-M updated:
+
+
Minor grammar edits to the text that tells you that your thirst is dealt with but no blood power is given. balance: Vampires are no longer able to drink get power from ckeyless humanoid monkeys, they will now need to hunt down actual characters with ckey to get power.
+
+
Shadow-Quill updated:
+
+
Mass drivers now need two rods/cable coil instead of three to construct.
+
The RD's office door can now be opened by the RD, instead of by just the Captain.
+
Science lockdown can now only be (de)activated by the RD, instead of any scientist.
+
Using a health analyzer in-hand will switch the verbosity.
+
You no longer have to unscrew a plating to repair it.
+
The shivering symptom in virology now properly chills people.
+
+
SteelSlayer updated:
+
+
Wizard rounds now end if all wizards and apprentices are either dead, inside cyborgs, or in MMIs
+
Re-enabled the wizard's hud. Wizards can now see their own antag icon along with seeing other wizard's and apprentice's icons
+
When a cult sacrifice target leaves the round via cryo, the game will reassign a new target for them
+
Added an alarm sound that plays for cultists when their sacrifice target leave the round via cryo
+
When a cult sacrifice target leaves the round via cryo, the game will update every cultist's notes to reflect the change
+
Adds a new verb named "Toggle Health Scan" to the ghost tab. While toggled on, ghosts can perform health scans on humanoids and cyborgs by left clicking on them
+
+
TDSSS updated:
+
+
syndicate fax machine to lavaland syndie base.
+
syndicate lavaland base self destruct now requires syndie access.
+
moved headsets in lavaland syndie base.
+
Gave the HoP fax long-ranged faxing capabilities.
+
midround event spawned xeno larva now need less time to grow up and evolve.
+
cult talisman got unique icons to tell them apart
+
mining hardsuits come with helmets now again
+
+
Tayyyyyyy updated:
+
+
Whether you join the ERT is no longer determined by how fast you click "yes" on the prompt.
+
Drag and drop support and 20 seconds to pick ERT role instead of 15
+
Fix extra newline after field and disable Github Flavored Markdown in papers (normal markdown still works)
+
autogenerated papers no longer appear as HTML code
+
message window links added to PM send receipt
+
Many shuttle flight directions fixed
+
+
TheSardele updated:
+
+
All-In-one Grinders can now be constructed and upgraded
+
All-In-one Grinders now produce more reagents when upgraded.
+
Icon for cybernetic eyes
+
Sleeping while drunk no longer makes you more drunk.
+
+
dovydas12345 updated:
+
+
Fixes being able to pick up chairs and stools when you have items in both hand or when you don't have hands.
+
Adds a ERT shuttle console which is accessible to ERT members
+
+
farie82 updated:
+
+
Rigging a crate now doesn't delete your coil stack anymore but instead uses 15 of it. Borgs can use it safely again
+
+
kazboo updated:
+
+
adjusts the hierophant blast layer to make for it to always be below the effect. this should be the case already due to mouse_opacity, though for some unknown reason, it just doesn't work sometimes, so this should fix it.
+
+
+
12 August 2019
+
AffectedArc07 updated:
+
+
Panic Bunker
+
+
Allfd updated:
+
+
Panthers can now see in the dark.
+
+
Arkatos updated:
+
+
You can ctrl-click any action button to lock/unlock its position
+
All actions buttons now start with their position locked
+
+
Citinited updated:
+
+
Mappers have a new tool that creates a fully functional cycling airlock.
+
+
CornMyCob updated:
+
+
The cursed heart you get from necropolis chests is now the one that heals you.
+
+
Couls updated:
+
+
Diagonal movement
+
Input subsystem(numpad targetting, press numpad 8 multiple times to target eyes and mouth, numpad 6 or 4 to target arms and press them again to target hands and numpad 1 or 3 to target legs and press them again to target feet) taken from https://github.com/tgstation/tgstation/pull/32751
+
change confused status to have you move diagonally randomly in the direction you're headed if not too confused(now you can drunkenly walk down the hall)
+
clients are now children of datums like everything else in BYOND taken from https://github.com/tgstation/tgstation/pull/20394
+
AZERTY and numpad targetting preferences
+
Reworks the biohazard event to have a chance of giving a randomized advanced disease with 6 varying symptoms instead of a preset disease.
+
change how bone breakage is calculated
+
can now butcher koi for salmon meat
+
adds a line to alert people as to why they're not getting blood from the monkeys
+
The vampires are finally off their monkey diet, theycan now suck blood from players and humanized monkeys
+
Symptoms are now correctly generated for level 7 biohazards
+
Borgs can now cycle modules with X again
+
Ahelp message is less confusing
+
F2 (say) F3(ooc) F4(me) buttons have been restored tweak:when numpad targetting is off you can use numpad 1-4 to change intents tweak:pressing shift before any of the intent buttons doesn't change intents(for people with shift+1-4 macros) tweak:backspace now sets the focus to the chat bar
+
fixes the runtime caused by running keyloop for clients
+
Preferences not saving properly
+
issue with preload_rsc
+
Restore hotkey mode
+
Q no longer drops items as a cyborg on AZERTY mode
+
Automatically offload ore you're carrying to an orebox you're dragging
+
typing indicators show up again
+
TG waddle component, clowns can now optionally waddle, penguins always waddle. Ctrl Click clown shoes in hand to toggle waddling
+
Added invismin macro back to F9
+
stealthmin macro removed from F9
+
+
Crazylemon64 updated:
+
+
Fixes a bug that would cause ghosts to teleport their bodies sometimes
+
+
Dave-TH updated:
+
+
The syndicate uplink is now complete with a new spooky background. Very neat!
+
+
DoctorDrugs updated:
+
+
Adds additional roundstart miner slots and the additional gear required for them to do their jobs
+
+
Fox McCloud updated:
+
+
Fixes being able to sharpen toy double-bladed energy swords
+
+
IAmBigCoat updated:
+
+
Added explosion warnings to medbeams, because medbeams can cause explosions. DON'T CROSS THE BEAMS!
+
+
Ionward updated:
+
+
Fixed vox jester uniform not appearing correctly.
+
species specific fit underwear for greys
+
+
KasparoVy updated:
+
+
Re-adds the ability to see in the dark. Adds overlays for each level of darksight (>=8,7,6,5,4,3,<=2).
+
+
Kyep updated:
+
+
Round time (h:mm) and station security level (green/red/blue/etc) are now visible on our server hub entry.
+
Round time is now visible to all player-controlled mobs in their status panel (including simple animals).
+
Admins using the 'MOST' attack log setting no longer see player-v-NPC combat, or any attack logs generated in the admin room, admin testing area, thunderdome arena, or lavaland syndicate base. Prevents admins being spammed with attack logs.
+
Heads of department may now issue department-specific medals to members of their department.
+
+
Markolie updated:
+
+
Humans and mice that are secretly blobs now have an antagHUD icon.
+
All hivemind languages now display follow links to ghosts.
+
Announcements, whispers (with ghost ears) and cultist messages are no longer displayed in the lobby.
+
The sentience event no longer triggers a huge number of ghost polling messages.
+
When xenomorphs are damaged, their health HUD now updates properly.
+
Custom title for ghost notifications now work properly.
+
Fixed double admin commands in the grenade priming message.
+
Ghosts will now always see whispers/zero pressure speaking if they're on the screen with the mob speaking.
+
Ghosts with ghost sight enabled will no longer see emotes from clientless mobs.
+
The prison labor point system has been refactored so it works properly.
+
Plating can now be removed (exposing the baseturf) using a welder.
+
All remaining Lavaland ruins have been ported over from /tg/.
+
All chairs on shuttles have been replaced with brand new shuttle chairs.
+
Tribal splints have been added to the game, which can be crafted with two bones and one piece of sinew.
+
The Lavaland Syndicate base now has a defibrillator and mounted defibrillator. The animal hospital now has a mounted defibrillator.
+
The Ash Walker storage area now comes with an advanced medkit instead of a regular one and one set of medical splints. It also comes with aloe vera, comfrey and wheat seeds.
+
The water tank in the Ash Walker nest has been replaced with a puddle.
+
The items in vending machines on the beach ruin and animal hospital are now free.
+
Fixed an issue where slimes wouldn't take damage from water in space.
+
It is no longer possible to unanchor the surivval pod storage units.
+
Drinking from a beaker now only applies the effect of five units of the ingested chemical, instead of the entire volume of the beaker.
+
Resolved an issue where beaker attack logs were reversed.
+
Moving through portals very quickly no longer breaks movement.
+
+
Quantum-M updated:
+
+
New sprites for vampires being "hungry".
+
New sprite for vampire usable blood count.
+
New sprites for the safety muzzle.
+
Safety muzzle (aka the anti-bitting one) can no longer be resisted out of.
+
Vampires can now suck blood from monkey mobs (e.g. monkeys, stoks, etc.) for sustenance but do not get blood power points.
+
RnD is no longer able to print out any telescience boards.
+
+
SteelSlayer updated:
+
+
Gives vampire thralls an objective, which can be viewed in their notes
+
Increases the size of the enthralling message seen by newly created vampire thralls
+
Vampire thralls are now stunned briefly (about 3 seconds) upon being enthralled
+
The AI's robot control window now allows you to see and interact with available bots again
+
+
TDSSS updated:
+
+
cult teleport runes and similar powers now work on z levels 9-12
+
+
Tayyyyyyy updated:
+
+
Inputs sanitized
+
autocomplete input mishandling single quotes (you can teleport to Wizard's den now)
+
newlines not working in CC announcements
+
players not being able to send single quotes in ahelps or PMs
+
robots not being able to pick their name
+
+
TheSardele updated:
+
+
Lowers throwforce of drinking cartons from 15 to 0
+
Bees no longer inject venom when nuzzling
+
Sec pod pilots can now spawn with the loadout security armbands
+
It is no longer possible to raise zero to -infinity fingers using the *signal emote
+
Earmuffs now properly protect you from vampire screeches no matter what you are wearing on your other ear
+
+
Ty-Omaha updated:
+
+
Reworded permanent bans to non-expiring bans.
+
Door remotes now add to admin-only hidden fingerprint list
+
Gave plastic surgery to line 364 of atoms.dm
+
+
and DominikPanic updated:
+
+
Limits IC notes
+
+
datlo updated:
+
+
Free Golems are now a lavaland ruin spawn instead of a space ruin spawn.
+
Free Golems must now purchase their shuttle board for 2000 mining points before being able to fly their shuttle.
+
Added a shuttle recall console at the golem lavaland spawn point so that golems can always recall the shuttle back to lavaland
+
The Free Golem Ship can now move to the Construction Site, the Derelict, or back to their Lavaland spawn.
+
The Free Golem Ship has been redesigned with an open floor plan, removing most of its interior walls for extra space.
+
Free Golems no longer get a free kinetic accelerator on their ship.
+
New crit species with below -100 health will be considered dead for hijack purposes, and will not interrupt a shuttle hijack attempt.
+
Fix some cases of traitors getting conflicting objectives, such as assassinating and protecting the same target.
+
+
farie82 updated:
+
+
Beepsky will now respect your disguise again. No more looking right through that gasmask
+
Medical and security HUDs now use the correct way to identify somebody. They will see the same as you do on your screen.
+
You will now get a job icon in the sec HUD when you use your PDA as ID. It'll use the PDA's assigned job.
+
Ticket takes now ask for confirmation if you want to take an already assigned ticket.
+
Blindfolds are now craftable from 3 cloth. For those vampire prisoners you want to keep in check
+
Empty beaker button from the PANDEMIC is now replaced with Empty and eject beaker
+
List AFK players is now a verb for admins to use
+
Adds the AFK auto cryo system. By default it won't affect players unless they activate it themselves by setting the preference in their game preferences tab.
+
The syndicate can't use meta warfare no more. Advanced pinpointers no longer crash the server
+
+
iantine updated:
+
+
Mouse suicide
+
+
improvedname updated:
+
+
adds lasagna
+
+
kazboo updated:
+
+
changed the display name shown to a player upon being frozen in a manner that only the admins ckey is displayed, not the character name along with it
+
+
+
08 July 2019
+
Arkatos updated:
+
+
Clicking on a health doll icon will now check you for injuries
+
Rechargers now show their contents and charge status on close examine
+
Smartfridge will now try to put an item in your hands after vending, if able
+
+
AzuleUtama updated:
+
+
The cybernetic implant bundle can no longer be bought by traitors.
+
+
Citinited updated:
+
+
Alt-clicking the RPD now brings up a radial menu with rotate, flip, and delete modes accessible. The main interface remains unchanged.
+
Writing in blood can't be done while dead or incapacitated any more
+
You can't write stuff in blood at a distance any more
+
+
Couls updated:
+
+
lantern sprites
+
typo in msg
+
+
Improvedname updated:
+
+
Explorer suits now properly hide tails
+
+
JKnutson101 updated:
+
+
Fixed Construction Permits deleting themselves prematurely.
+
+
Kyep updated:
+
+
fixed a bug with biogenerator.
+
+
Markolie updated:
+
+
Ghosts can now see all PDA messages when enabled through a preference setting.
+
The Mask of Nar'Sie transformation buttons have been removed, as the mask was removed a long time ago.
+
+
Shadeykins updated:
+
+
Changed Quarantine, NT Default, Aggressive, and Corporate AI lawsets. balance: Reduced the ability for NT Default AI's to murder people just because.
+
Removed several redundancies in Aggressive lawset.
+
Fixed a few subject-verb disagreements (is -> are).
+
+
Tayyyyyyy updated:
+
+
paper supports markdown as well as pencode
+
Autocomplete for ghost buttons
+
PMs window scrollable
+
Fix a bug where a player who reconnects is still shown as disconnected
+
+
datlo updated:
+
+
Fix an antag rolling exploit.
+
+
+
30 June 2019
+
Crazylemon64 updated:
+
+
SDQL2 no longer allows a macro argument
+
+
+
28 June 2019
+
AffectedArc07 updated:
+
+
SSticker
+
You can no longer force-start a round unless its fully initialised.
+
Tweaks some preference orders
+
Moved a global define
+
+
Akatos updated:
+
+
Smartfridges now visually show approximate number of items inside
+
+
Arkatos updated:
+
+
Ragin' Mages gamemode should now be playable without any major issue
+
Slaughter and Laughter Demons no longer have duplicit objective shown at the Round End
+
Laughter Demon is now properly called Laughter Demon instead of Slaughter Demon in the role polls
+
Improved wording and fixed mistakes in Wizard and Ragin' Mages gamemodes
+
Wizards are now properly polled in the Ragin' Mages gamemode
+
You can no longer buy Summon Ghosts spell in the Ragin' Mages gamemode
+
You can no longer buy Bind Soul spell in the Ragin' Mages gamemode
+
Deck of tarot cards renamed to Guardian Deck in the Wizard spellbook
+
Rituals and Challenges categories merged into one in the Wizard spellbook
+
Laughter Demon is now slightly weaker compared to the Slaughter Demon
+
Bottle of Ooze now creates a magical morph instead of a normal one. Magical morph is capable of casting smoke and forcewall spells.
+
Visible ghosts will now get a special description about their visibility
+
Removed Cursed Heart from the Wizard spellbook
+
Changeling verbs replaced with action buttons
+
Changeling ability descriptions updated
+
Added custom icons for changeling action buttons
+
Added movement animation for mice, chickens and killer tomatoes
+
Added inhand sprite for eggbox
+
Added inhand sprites for all types of soaps
+
Added inhand sprite for small parcel
+
Added inhand sprite for sechailer
+
Added inhand sprite for bag of holding
+
Added new system for outputting contents of smartfridges
+
Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one
+
Fixed and improved some descriptions regarding Blob offspring
+
Fixed a case where ghosts had an extra ghost icon visible on them
+
Fixed a case where some ghosts were too bright
+
You are now unable to swap forms with another changeling
+
You can no longer hiss while muzzled
+
Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability
+
Changelings in the lesser form can now toggle Augmented Eyesight ability
+
Changelings are now removed properly via Traitor Panel
+
Changelings do not get their action buttons bugged when using Swap Forms ability now
+
Action buttons should update their cooldown statuses more reliably
+
Changelings should now correctly receive their action buttons
+
Changelings now do not steal action buttons from other changelings
+
Added new Boo! spell icon
+
+
Christasmurf updated:
+
+
Fixes a random pixel on the leather shoes
+
+
Citinited updated:
+
+
Boo affects APCs again
+
Boo no longer fully charges when you enter your corpse
+
The button to close radial menus is much more obvious and easily-clickable now
+
Destroying a disposals trunk should no longer occasionally delete things held inside it.
+
Fixes conveyor belts not moving items spawned via an autolathe. (And other possible behaviours when machines switch between speed and normal processes)
+
Ports liquid dispenser sprites from tgstation.
+
+
Couls updated:
+
+
Only names from the manifest will be used for syndicate code phrases
+
randomly generated people names from syndicate code phrases
+
Medical category to exosuit fabricator with implants and cybernetics
+
t-t-t-typo!
+
codephrase names no longer appear blank
+
+
EmanTheAlmighty updated:
+
+
Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult.
+
+
Evankhell561 updated:
+
+
Portable Seed Extractor designon the protolathe.
+
+
Fethas updated:
+
+
Fixes an oversight from the lavaland port invovling Laz injectors and sentience typing that didn't carry over from tg.
+
+
Fox McCloud updated:
+
+
Future proofs the coming Ticker subsystem
+
Removes the Process Scheduler
+
+
Improvedname updated:
+
+
Cargo miner starter kit crate will no longer include a ID
+
+
Kyep updated:
+
+
Ported XKeyScore from TG.
+
New system to securely link ingame/forum accounts
+
Removed old insecure 'link discord account' system
+
unanchored vending machines will no longer generate a runtime error when throwing products at people.
+
Disarming/grabbing a door with IDSCAN disabled no longer results in a can_admin_interact runtime error.
+
Terror Spiders no longer trigger their special attack when nuzzling someone on help intent.
+
+
Markolie updated:
+
+
Chameleon items now use the appropriate species icon.
+
Lighting now respects color blindness again.
+
pAI flashlights now work properly.
+
Rotatium can now be created properly.
+
Ghosts can now transition through space again. This is now done by clicking on the edge of space.
+
Added custom explorer gas mask sprites for Grey/Drask.
+
Added a lantern to the Hermit cave.
+
Added a bone setter, bone gel, FixOVein, sterile masks and sterile gloves to the Lavaland Syndicate base.
+
The pickaxes on the Lavaland labor camp have been replaced with safety variants. The flashlights have been replaced with lanterns.
+
Fixed many species missing sprites for explorer gas masks and jumpsuits. They now use the humans icons until we have custom sprites.
+
Resolved an issue with piping not working on the Lavaland mining bases.
+
Fixed all items being free in the mining vendor.
+
Fixed improper wiring to the turbine in the Lavaland Syndicate base.
+
Fixed the Lavaland Syndicate base oxygen sensor not working.
+
Moved the pipe dispenser in the Lavaland Syndicate base so it doesn't clip with tables.
+
Fixed the Lavaland Syndicate base incinerator doors not working.
+
Ash Walkers now once more have fine manipulation. Their lack of fine manipulation caused unintended side effects (such as them being unable to mine).
+
Ash Walkers (and other ghost spawner roles) can no longer be antagonist targets or become antagonists through the antagonist creation.
+
Fixed the Lavaland Syndicate base incinerator buttons not working.
+
Fixed the Syndicate communication agent spawning with a broken voice changer mask.
+
Fixed the Disk Compartmentalizer not having a sprite.
+
The Ancient Goliath now has a small chance of spawning instead of regular goliaths.
+
Survival capsules now have a NanoMed.
+
Water bottles now behave as glass containers.
+
The behaviour of glass reagent containers has changed. When used on non-mobs, contents will now only be spilled on harm intent. When used on mobs, on any intent aside from harm the contents will be fed to the mob like regular drinks. On harm intent it will still be spilled.
+
Hairless hide can now be made wet using most sources of water (minimum volume of 10), instead of just washing machines.
+
Added some additional offstation role checks to ensure ghost spawner roles don't become antagonists, are kidnap targets or are counted towards station goals.
+
Fixed some piping in the Lavaland Syndicate base incinerator and made sure the vault door starts locked.
+
Fixed the Lavaland swarmers getting stuck on propulsion.
+
Fix goliath tentacles sometimes being left behind.
+
The walls around the Lavaland Syndicate base turbine have been coated, to prevent them from starting a plasma fire in the base.
+
Syndicate agents can now access the air alarms on the Lavaland Syndicate base.
+
Air alarm control computers can no longer access the air alarms on the Lavaland Syndicate base.
+
Fixed the disk compartmentalizer/drying rack missing a sprite under certain circumstances.
+
Fixed the Lavaland Syndicate base triggering atmospherics alerts.
+
You can now properly place tiles on basalt.
+
An exploit with the sheet multiplier has been fixed.
+
Portals can now be activated by clicking on them with or without an object. Ghosts can now also click on them to be taken to their destination.
+
Portals now warn admins when they are used to teleport megafauna.
+
The singularity can now eat basalt and chasms on Lavaland. They get turned into lava.
+
AI swarmers will no longer get stuck on effects (such as blood).
+
Fixed the spectral blade turning all ghosts visible.
+
Fixed a runtime with assigning outfits to mindless mobs.
+
Fixed certain alarms triggering despite being outside of station contact and the Syndicate base still triggering fire alarms.
+
Fixed being unable to put the wormhole jaunter in the belt slot.
+
Fixed the disk compartmentalizer not accepting disks.
+
Gutlunches and Gubbucks will now reproduce properly.
+
The necropolis chest cult clothing drop no longer spawns with a cult hood as well, as that's part of the suit itself.
+
Goliath steaks can now be eaten properly.
+
Fixed a stray light on the beach ruin.
+
Lavaland ruins should no longer spawn on the Labor Camp.
+
Ancient goliaths will now properly randomly spawn tentacles.
+
The labor camp will now spawn properly with a processing console.
+
Water turfs in the beach ruin (and other water turfs that previously didn't do so) will now properly apply water to you.
+
Ash flora is now anchored.
+
Gutlunches will now eat properly.
+
The tesla can no longer travel through wormholes.
+
Fixed an issue with honkbot construction.
+
+
Markolie and Ionward updated:
+
+
Added Tajaran, Vulpkanin, Unathi and Vox sprites for the explorer gas mask (thanks to Ionward!)
+
Added custom species sprites for the explorer suits and hoods (thanks to Ionward!)
+
Added missing surgical tools and a pet vendor to the animal hospital.
+
Added a custom cigarette vendor to the beach biodome ruin.
+
Added an autolathe and RPD to the Lavaland Syndicate base. Also added a custom cigarette vendor and made the vendors not charge money.
+
Added tiny fans to the mining base and labor camp exist.
+
A separate jobban for ghost roles has been added.
+
The alternative sink now has directional sprites. This resolves an issue with shelters having sinks facing the wrong way.
+
Fixed the Syndicate sleepers on the Lavaland Syndicate base pointing the wrong way when a ghost role spawns in.
+
Fixed Lava being removed by the staff of lava not working. Also added a missing warning effect when the staff is turning regular turf into lava.
+
Fixed random bookcases not spawning books (hopefully).
+
Fixed surgical drapes not having a sprite.
+
Fixed being unable to modify the GPS tag of shelters.
+
Fixed the Lavaland swarmers not eating anything.
+
The ash drake swoop attack is no longer incredibly loud.
+
The Syndicate base self-destruct is now much more powerful and capable of destroying the entire base.
+
The flavor text of Ash Walkers and Syndicate operatives now clarifies what they can('t) do.
+
Ash walkers can no longer use machinery.
+
+
Ported by Markolie and CornMyCob. Developed by many /tg/ coders updated:
+
+
The mining asteroid has been replaced with Lavaland.
+
+
Shadeykins updated:
+
+
Fixes a paper exploit.
+
Fixes rogue pixels on breath masks/gas masks for Plasmamen.
+
+
TDSSS updated:
+
+
Vampire rejuv wakes you up if you're asleep now
+
Cling epinephrine wakes you up if you're asleep now
+
Sling glare popup no longer lists invalid targets for glaring
+
+
Tayyyyyyy updated:
+
+
Messages window (My PMs in OOC tab)
+
You no longer have to wait on others for ERT spawning
+
Admin jobs no longer announced
+
+
Terilia updated:
+
+
Added the Donksoft sniper into the Trader spawnpool.
+
+
Ty-Omaha updated:
+
+
Changed admin take ticket color from neon green to Asay pink
+
Manual bans now auto-note
+
Stops projectiles using the legacy system such as emitters from hurting shield blobs due to an exploit where it would always hit or go through.
+
+
craftxbox updated:
+
+
Highlight string uses regex
+
Removed jquery mark
+
+
datlo updated:
+
+
The Syndicate will no longer hire golems as agents.
+
Banana juice and Banana honk will now heal everyone with the Comic Sans mutation instead of checking for the clown job
+
Nothing will now check if the player has an active vow of silence instead of checking for the mime job
+
Ghosts will no longer get the wrong role offered when a nukie spawns a borg and will properly be informed whether they will spawn as a nuke ops or a syndi cyborg.
+
+
dovydas12345 updated:
+
+
Fixes cryopod removing ambulance, secway keys
+
Fixes cryopod recovering the invisible headpocket item
+
+
farie82 updated:
+
+
Can't use cuffs now while you have antidrop
+
can_equip now checks if you have the limbs required to equip something
+
Reverts the string highlighting done by regex
+
+
iantine updated:
+
+
Skrell *warble emote
+
+
uc_guy updated:
+
+
Theft objective locations hints now ignore the Centcomm Z level.
+
Adv. Pinpointer no longer targets items in Centcom Z level.
+
Fixed "Venus Human Traps" being invisible.
+
+
+
10 May 2019
+
AffectedArc07 updated:
+
+
Removes an infinite loop in the code
+
Removes unused code
+
Captains display case now actually has captains thumbprint lock on it
+
Morgue updates happen slightly better now
+
Fixes a minor NTTC issue
+
+
Arkatos updated:
+
+
Patch Pack is now craftable with a cardboard, costs 2 cardboard sheets.
+
Examine tooltip delay increased slightly
+
Examine tooltips now work properly on items in storage
+
Full toolbelts now spawn with randomly a colored cable coil
+
Added inhand sprites for belts
+
Species name now shows in a species theme color on examine
+
Added 4 new plushies
+
+
Couls updated:
+
+
necromantic stone now forces the ghost back into the body as a skeleton
+
allow skeletons to give up their bodies and offer control to ghosts
+
+
Crazylemon and Fox McCloud updated:
+
+
Fixes toggles not properly saving
+
+
EvadableMoxie updated:
+
+
Added the Nanotrasen Hospital Vessel Asclepius, able to be deployed by admins.
+
Admin shuttle now requires ERT clearance instead of admin clearance.
+
Admin shuttle now has a navigation computer and tiny fans at the airlock.
+
+
Fox McCloud updated:
+
+
Fixes a few instances generating log spam relating to z-level tracking
+
Fixes weird behavior with ghosts being able to trigger a few things by crossing over them
+
Fixes drifting ghosts
+
+
Ionward updated:
+
+
Updated the cautery sprite!
+
+
KasparoVy updated:
+
+
Adds a verb to eyewear you can use to adjust them so they appear above or below masks. Discover interesting combinations and enjoy a cool look.
+
+
Kyep updated:
+
+
Trying to latejoin a round with no open job slots now results in an informative error message, rather than broken-looking blank window.
+
Added new bonus loadout items for higher-tier patrons. Also gave admins access to patron items, and ensured that during custom events, you see the custom event announcement when you connect.
+
You can now identify when someone is using internals from a tank in their pocket, without having to remove the tank.
+
punching a windoor no longer generates a runtime error.
+
cryogenic_liquid/envenomed_filaments blobs no longer generate runtimes when their blob special attack hits mobs that do not process reagents
+
fixed $5+ donors not getting extra loadout points.
+
+
Markolie updated:
+
+
Ambient occlusion had been added to the game. This represents a shadowy effect on most objects. It can be turned off through the game preferences menu.
+
Our lighting system has been updated to /tg/'s latest version. Hopefully this means we'll have less lag later in the round.
+
Night vision has been modified. There are now three levels of night vision. Certain creatures that were previously able to toggle night vision can now switch between all levels. Thermals now give some night vision.
+
Mesons now no longer fully light up non-visible turfs. It uses slight darkness instead.
+
Syndicate operatives may now purchase a chameleon bundles (2TC), which allows them to disguise not just their jumpsuit, but all of their equipment. They can change individual clothing as well as the outfit as a whole.
+
When using a voice changer, NTTC will no longer default to an "Unknown" job: it'll still use the assignment on your card to prevent meta-gaming. Always combine a voice changer and a Syndicate ID.
+
Admins with advanced admin interaction toggled on can now interact with the small airlock buttons.
+
The steel_rain runtime fix has been re-applied.
+
The propulsion on the admin shuttles has been fixed. The shutters on the south side of the hospital shuttle now point the right way.
+
Nuclear Operative reinforcements now spawn with a properly counted agent designation.
+
Fixed an issue where a mob's sight wouldn't update properly in certain cases, such as being revived.
+
Resolved an issue where the lobby would be bright white when being sent back.
+
Resolved an issue where the ambient occlusion preference wouldn't update properly in the lobby.
+
Resolved an issue where clicking on a windoor would no longer prevent it from auto-closing.
+
When a nuclear operative chooses to play as the borg instead of operative using the cyborg teleporter, ghosts will now be informed of this in their acceptance message.
+
Resolved an issue where cameras couldn't take pictures of non-dynamic lighting areas, such as the holodeck or space.
+
Resolved an issue where mobs would appear above water.
+
Resolved an issue where radiation storms would make lighting invisible in space.
+
Simple mobs no longer retain their X-Ray upon being revived.
+
Applying brute/fire damage through the View Variables menu for non-humans has been fixed.
+
NTTC regex has been disabled due to an urgent security issue.
+
+
Mitchs98 updated:
+
+
You can now order a Pig Crate from Cargo for 25 points.
+
+
TDSSS updated:
+
+
typo on sst shuttle console
+
opening turret covers now stay on top of their turret.
+
+
Twinmold93 updated:
+
+
Adds Server Time to the Status Tab for Admins.
+
+
farie82 updated:
+
+
Transforming into another species will now retain the items correctly. Example clings will keep their armblades and they won't get stuck with a non existing armblade they can't put back
+
Devour and regurgitate use forcemove now. So no being buckled inside an alien
+
+
fludd12 updated:
+
+
Project Mind now has a corollary ability, Scan Mind. Now communication can be two-way!
+
+
variableundefined updated:
+
+
Simple animals actually use the new subsystem now
+
What was NPCAI is now renamed to NPCPool - Its the functional equivalent of what it is in tg
+
Simple animals actually run on subsystem instead of a process now.
+
idleNPCpool has been added reducing performance impact of hostile simple animals
+
NPCAI Process (That run both SNPC and SimpleAnimals) that was somehow left out by me
+
SNPC & assocaited NPCAI Subsystem
+
Some of space hotel's functions.
+
Bodysnatch gland.
+
process_ai has been deprecated
+
+
+
02 May 2019
+
AffectedArc07 updated:
+
+
ssMapping
+
Gateway and space ruins are now loaded with ssMapping
+
Master Controller
+
Darkmode chat department colors match NTTC theming now
+
SSvotes
+
SSradio
+
SSevents
+
SSholiday
+
We no longer check if its Christmas every tick. Dont ask.
+
SSalarms
+
+
Arkatos updated:
+
+
Shadowlings now have a slightly bigger colored text when speaking in the Shadowling Hivemind
+
Replaced title2.ogg music with a higher quality version
+
Shield Blobs automatically spawned around Blob Cores now give no refund upon removing. No freebies.
+
Added new Wizard Spell - Summon Ghosts! This nefarious spell will make all ghosts visible to the living. Be careful though, as while they cannot harm you in any way, they might prove a bit.. annoying. Costs 0 points in the Wizard's spellbook.
+
Ghosts now orbit around their followed targets
+
Added new Shadowling Ability - Null Charge! This new ability allows Shadowling to completely drain an APC of it's power after a moderate delay. Shadowling must not be interrupted, or the whole process will fail.
+
Added custom icon for the Null Charge ability
+
Shadowling Drain Life ability removed
+
Added Observer HUD buttons for Jump to Mob, Orbit, Re-enter corpse, and Teleport
+
Added custom icons for Observer HUD buttons
+
Added Floorbot color variants. Different toolboxes will result in a differently colored Floorbots. One even might be a little stronger than others..
+
Added sprites of Floorbot color variants
+
Fixed incorrect amount of required floortiles for the Floorbot in the crafting tab
+
Added cancel button to Wizard teleportation scrolls
+
Added an option to grant Martial Arts via administrative Var menu
+
Toggling hardhat light on/off now correctly updates wearer's sprite
+
Added deathsound for Silicons
+
Dice will now roll when thrown
+
Added sound when adding or removing IDs from ID modification computers
+
Added cancel button to transfer amount from stack menu
+
Alt-click is a new shortcut to take a custom amount from stack
+
Added shortcuts for handling pumps, volume pumps, filters, and mixers. Ctrl-click these devices to turn them on/off and Alt-click them to set their output to maximum.
+
Added ability to rename pumps, volume pumps, filters and mixers with a pen.
+
Added sound for throwing bolas
+
Added hitsound for all types of bolas
+
Added AntagHUD to everyone at the round end
+
Circuit Boards now show their required components on examine
+
Revenants now have randomly generated flavor names
+
You can shift-click any action button to reset it's position. Alt-click on Hide Buttons will reset all action buttons to their default positions.
+
Pill Bottles are now printable in the Autolathe. You can find them in the Medical section, and each costs 80 metal and 20 glass to print.
+
Puts beakers in your hand upon eject from chemistry machines
+
Cardboard can now be made in the Biogenerator
+
You can now hotswap tanks in a canister or gas pump by clicking it with a new tank!
+
You can now also close a canister's valve and remove the tank inside it by alt-clicking it.
+
Added examine toolptips. Hover over any equipped or hold item for a little while and it will display the item description as a tooltip.
+
Ghost teleport verb will no locker flicker when used
+
Alt-click now opens and closes fire extinguisher cabinet
+
Fire extinguisher cabinet now properly updates it's sprite correctly when putting fire extinquisher inside the cabinet
+
Fire extinguisher no longer sprays when put into fire extinguisher cabinet with a safety off
+
Added sound for opening and closing fire extinguisher cabinet
+
Added new torch sprites
+
Torch light color is now orange instead of red
+
Torch sprite now correctly shows all inhand sprites
+
Blob Rally Spores power is now free to use
+
Blob mobs can no longer speak while being dead via Blob Broadcast
+
Blob structures now properly show working animation
+
Added new sprites for variants of Blob resource, factory and storage structures
+
Added inhand sprites for winter coats
+
Carps now spawn with a random color! There might even be some really rare ones..
+
Added carp color variants sprites
+
+
Arkatos and Paradise community: updated:
+
+
Added Tip of the round to a pre-game lobby
+
Added Show Custom Tip admin verb
+
Added Give Random Tip OOC verb
+
+
Citinited updated:
+
+
You can no longer turn transit turfs into foamed metal flooring.
+
Foamed metal floors have a sprite now.
+
Pipe dispensers (the big ones) now work again.
+
Cooldown on pipe dispensers reduced to 0.4 seconds, down from 1.5 seconds
+
+
CornMyCob updated:
+
+
The plasma cutter now cuts through multiple rock tiles.
+
+
CthulhuOnIce updated:
+
+
you can smell dead bodies, even if someone else shouldn't
+
+
Fethas updated:
+
+
Cluwne suits should no longer fall off cluwnes from being fat.
+
+
Fox McCloud updated:
+
+
CQC has been updated; a few combos are more powerful
+
cost increased to 13 TC
+
CQC is now nuke ops only
+
gloves of the north star restriction on CQC removed
+
CQC disarms will now take the item from your opponent
+
CQC blocks melee weapons and a couple of stun weapons and not everything now
+
Reagents will now adjust to the body temperature over time as opposed to all at once
+
Strange Reagent will work 25% of the time with TOUCH based reactions
+
Strange reagent will revive whether there's a ghost or not (can use SR on clientless mobs now, like monkies)
+
SR puts the occupant back in their body automatically
+
Cloners that eject their messes will now eject the unattached organs
+
the message for brain death will now properly and only occur when they have truly died from brain damage
+
Fixes being able to attain brain damage over 120
+
Updates nations. Updates nations so hard right into the void
+
Plasma fires should burn a bit faster now
+
Bleeding will now stop at the temperature at which cryoxadone heals
+
Fixes a few potential exploits with forcing chem, dust, and explosive implants activating with the deathgasp emote, prior to death
+
Tesla can't zap cameras and other disposal structures anymore
+
Simple mobs can now be shocked
+
Electrocution damage scales a bit more linearly up to its maximum potential instead of being heavily random
+
Fixes being able to shock yourself with TK, at range, on electrical equipment
+
simple mobs can now be shocked by the tesla and other sources
+
Fixes goats not attacking people
+
Goats will eat glowshrooms
+
Goats will eat full grown diona
+
Remapped toxins to be more compatible with the modern age
+
updates plasma and N2O sprites
+
Fixes not being able to look at a turf if it had plasma/N2O on it
+
cold turfs no longer become icy
+
Cryostylane makes turfs icy
+
Icy turfs are slippery; wear magboots to counteract the effect. Watch your head!
+
Fixes grammar of slipping on turfs; no more "you slipped on floor" or "you slipped on wet floor"
+
removes ponies
+
object and fast processing are now proper subsystems
+
Fixes multi-spawn blobs
+
Powersinks drain rate increased, but they also explode a bit sooner
+
Multitools display total power, load, and free power
+
Fix emitter sparks sparking at the location of emitters where biult as opposed to emitter current location
+
+
Ionward updated:
+
+
Added new mantles! Check the ClothesMate, or in department head's lockers.
+
+
KasparoVy updated:
+
+
Adds striped normal-height socks.
+
Vox can now wear whatever undergarment they want.
+
Removes flesh from shredded Vox uniform sprites.
+
Armalis can no longer wear undergarments. They didn't fit, anyhow.
+
Underwear no can no longer lock up the character creator.
+
+
Kyep updated:
+
+
bans issued by admins via the Player Panel no longer incorrectly omit IP/etc information
+
admins issuing permanent bans are no longer presented with an "ip ban?" prompt, as all bans include IP/CID information now. This prompt was a legacy thing from back when the filesystem was used to store bans, and hasn't ever affected how DB-based bans were stored.
+
Added a config file option which allows SSD crew members to be moved to cryo after a defined amount of minutes.
+
Added a config file option which causes most people trying to attack/loot/interact with a SSD character to need to confirm they've read the rules before being able to do so.
+
Fixed an error message being inappropriately generated for admins when someone signs up as a pAI.
+
The ID computer now color-codes potential job transfer options, highlighting good choices for a job transfer in green, and bad ones in gray.
+
Taking a job transfer now gives you playtime based on your new job, instead of incorrectly still giving you playtime based on your old job.
+
Job transfers to karma jobs are now possible - if you have the job unlocked.
+
Attempting to bypass a job ban via a job transfer now generates a warning to all online admins.
+
Refactored and improved our entry on the server hub.
+
Fixed a runtime in job_exp.dm
+
+
Markolie updated:
+
+
Safes can now consist of more than two tumblers.
+
All safes now have three tumblers by default, instead of two.
+
The safe opening mechanism has changed slightly. This is described on the safe cracking UI.
+
The hardsuit equipment lockers on the Syndicate Nuclear Operative shuttle have been replaced with suit storage units. Suit storage units now have a separate slot for magboots.
+
Nuclear Operatives can now purchase reinforcements. These reinforcements cost 25 telecrystals each.
+
A number of new ammunition and weapon bundles have been added for Nuclear Operatives.
+
For every ten players on the server, the Nuclear Operatives now receive 2 extra telecrystals.
+
The Syndicate borg spawners have been separated into three separate spawners, one for each type of Syndicate cyborg. Their prices have been modified.
+
Saboteur borgs now spawn with thermals.
+
The Syndicate borg and exosuits have been moved to a new category, "Support and Mechanized Exosuits".
+
Existing bundles and telecrystal purchases have been moved to a new category, "Bundles and Telecrystals".
+
There are now more spawn points for nuclear operatives on their base. The number of operatives spawning has not been changed.
+
Spawning nuclear operatives through the traitor panel now causes their ID to be properly updated.
+
Shuttles no longer leave behind their propulsion.
+
AZERTY hotkey mode users can now switch between regular mode and hotkey mode properly using TAB again.
+
Jumpsuits are now removed by clicking instead of clicking and dragging.
+
Removed a useless message that would be sent to admins whenever a drone joins the round.
+
Fixed an issue where admins would receive a message whenever someone joined up as a pAI.
+
+
McDonald072 updated:
+
+
You can no longer examine or teleport things using clipboards
+
+
Quantum-M updated:
+
+
Two multicolor pens to the Internal Affairs Office
+
+
TDSSS updated:
+
+
nukies can buy plasma grenades again
+
+
Ty-Omaha updated:
+
+
Moves AI admin log to the all preference
+
+
dovydas12345 updated:
+
+
Fixes normal cameras spooking non-chaplains even when they don't capture any ghosts
+
+
farie82 updated:
+
+
Makes puke less lag inducing
+
Puke can now appear on all kinds of turfs except spess
+
Ticket messages now have their corresponding span classes. Making them easier to notice
+
PM's now shouldn't go to the wrong client anymore when the target left.
+
Cure text for Shock and Cardiac failure are more clear now
+
Ducttape gags can now be removed properly without spawning an invisible one in your hands
+
Windoors now give the airlock assembly electronics once deconstructed
+
Can't place runes in space anymore
+
Admins can now use all mhelp related things again
+
Fixed the toggle mentor ticket messages text
+
Vampiric glaring is logged now
+
Doctor delight and orange juice now heal again
+
Fixes admin PM's. Bwoinks are back on the menu!
+
Organs will now prompt a update_stat. Meaning that IRCs and the like now get revived when possible when you put their battery and brain in
+
The typing limiter option should now work for all edge cases. Such as dying while talking and such
+
Borgs health status now updates properly when removing and adding parts
+
You won't try to fix destroyed components in borgs anymore. Which resulted to lost materials and no healing
+
Borg analysers will now properly show missing components and won't show their damage if missing
+
Self diagnostics for borgs now also shows missing parts and destroyed ones
+
+
iantine updated:
+
+
Adds Lumi's vox suit fluff
+
+
uc_guy updated:
+
+
Players in the lobby no longer see cult speak.
+
+
+
08 April 2019
+
TDSSS updated:
+
+
Added missing vent in toxins mixing
+
+
+
07 April 2019
+
Arkatos updated:
+
+
Guardians can no longer change action intents on their own
+
Fixes #10900 - Guardians can no longer attack their host while inside them
+
Explosive and Support Guardians now get precise cooldown shown (instead of just static estimate) before their bomb and beacon abitilites are ready to be used again, respectively
+
HARM action intent icon for Guardians updated
+
Dehydrated Space Carp TC cost changed from 3 to 2
+
Shadowling Glare ability reworked - The further Shadowling is from their glared target, the shorter stun their target gets. Stuns also have a delay before they kick in, based on the distance, however targets will be slowed and muted before stun takes effect. Targets on the tile just next to them are still stunned and muted for 10 seconds without any delay.
+
Added victory message to the End Round messages in the Shadowlings Rounds
+
Shadowling Destroy Engines ability reworked. You now need to sacrifice non-ally target to delay the emergency shuttle arrival by 10 minutes, and shuttle will be unable to be recalled. This ability can be used only once across ALL Shadowlings.
+
Descriptions now show with a mouse hover over action buttons
+
+
Fox McCloud updated:
+
+
Fixes Russian revolvers triggering no matter where you clicked
+
Power gloves electric shocks can target anything now (still only damages mobs)
+
Power gloves electric arcs will bounce around (if it happens to target a mob though, it'll ground out and not bounce any more)
+
Power gloves cooldown lowered from 12 to 4
+
Power gloves heat up the turf they target
+
Using power gloves on disarm intent will weaken your target instead of dealing damage
+
CLF3, Phlogiston, and Fluorosulfuric acid all require greater volumes to achieve their upper damage limits
+
CLF3 and Phlogiston have lower minimum damage
+
Grey's treat water more closely to sulfuric acid (including passive damage while it's in them)
+
Grey's don't instantly purge all sulfuric acid from their system; it depletes at the normal rate, but doens't cause damage
+
Foam altered to be a bit more viable compared to smoke
+
Fixes being unable to view pill bottle inventory in some circumstances
+
Vending items from vending machines will try to put the item in your hands after vending
+
Vending machines with refill-canisters can be beaten apart and broken
+
+
Kyep updated:
+
+
Ghosting while alive, conscious, and a member of the crew will now result in your body being moved to cryo after 5 minutes, assuming your body isn't killed or restrained in any way in the meantime.
+
An AI that ghosts while alive gets a dismissable hint that they might consider using OOC -> Wipe Core instead.
+
Ghosting out of your body while you are alive, and an antag, will result in admins being informed, so that they may replace you as an antag if needed.
+
Empress of terror (admin-only mob) is no longer incorrectly prevented from laying brown spider eggs.
+
Admins are now able to spawn a queen of terror in a room without a vent. Previously, queens would not allow this. Now, this just results in an alert to admins (since its probably a mistake) and deactivates the mob AI (but leaves it available for player control).
+
If there are player controlled terror spiders, admins using check antags panel will now be able to see eggs/spiderlings currently growing on the station. These counters only count eggs/spiderlings on station, and ignore fake spiderlings.
+
Empress of terror's 'erase brood' ability no longer incorrectly causes mothers of terror to spawn spiderlings on death. sprite: Empress of terror now has its own sprite.
+
White spider infections have been nerfed a bit. They no longer provide passive healing or increase infection progress while their host/victim is in crit. Also, the first spiderling to emerge from an infection can no longer be a green. Finally, the eggs now self-delete after the third spiderling emerges, so even in the event they aren't treated with surgery, the host isn't left with confused movement forever.
+
+
Markolie updated:
+
+
Changing your hotkey mode now happens instantaneously and no longer lags.
+
An issue where the Hotkey Toggle button wasn't working has been fixed.
+
+
TDSSS updated:
+
+
upload consoles now tell you if you forgot to select an ai/borg before using an upload module.
+
trick revolver comes in a box, so you can tell what it is when getting it in a surplus crate.
+
+
farie82 updated:
+
+
Gives you the option to disable text popup spam. Aka if enabled you won't get popups after you pressed T and had a lagspike and you typed a sentence containing a lot of T's. Default is off
+
Now checks if OOC and LOOC are enabled before showing the popup
+
Adds a Mhelp ticket system
+
Take in the m/a-helps now actually takes the question
+
a/m-help followup responses using a-mhelp verb now get added to the last ticket like it should
+
Normal players can now see their open tickets using the My Admin/Mentor tickets verb
+
+
+
06 April 2019
+
Fox McCloud updated:
+
+
Fixes people popping out of cloning taking tons of damage
+
Fixes Teslium recipe
+
Fixes some reagents not causing status updates
+
+
Twinmold updated:
+
+
No longer costs toner to send a fax to Central Command
+
+
dovydas12345 updated:
+
+
Fixed diamond statue names and description.
+
+
farie82 updated:
+
+
Sec huds work again. No longer does the perp need glasses to be set to arrest. Cool does not equal arrest now
+
+
+
04 April 2019
+
Kyep updated:
+
+
Improved the interface for Syndicate Uplinks. They now clearly mark which items are hijack-only and which are not. If you attempt to purchase a hijack-only item without hijack, they will explain why you can't.
+
Atmos Gas Grenades (the uplink grenade kit) are now split into Knockout grenades (2 N2O grenades, 8 TC, available to all agents), and Plasma Fire grenades (2 plasma fire grenades, 12 TC, only available if you have hijack). This both makes knockout grenades more useful for normal traitors, and also prevents non-hijackers using a plasma fire grenade to cause massive casualties/damage.
+
Plasma Grenades and the Syndicate Bomb can no longer show up in surplus crates, or be discounted. This means while you can buy one if you intend to, you're not randomly encouraged to bomb your target.
+
+
+
03 April 2019
+
Fox McCloud updated:
+
+
Dramatically improves human life performance (sorry, doesn't fix your actual crappy real life)
+
Blobspores will additionally zomify all players who have 200 damage or more
+
Holoparasites will additionally die once their host has 200 damage or more
+
Fixes blob zombies who infect players who have no head being invisible
+
+
farie82 updated:
+
+
Death nettle can be picked up again
+
Auto cloning now doesn't clone a person more than once.
+
A person in the cloning scanner won't be scanned if he's already being cloned
+
+
+
02 April 2019
+
Alonefromhell & AffectedArc07 updated:
+
+
Fixed an edgecase compile error for spacehotel.dmm
+
+
Arkatos updated:
+
+
Added Medical Beamgun to a Syndicate Medical Cyborg
+
Appropriate antagonist sound theme now plays when an antagonist is selected via Traitor Panel
+
Cult sound theme now plays for a new cult converts
+
Traitor/Malfunction sound theme now plays for newly autotraitored crew/AI
+
+
AzuleUtama updated:
+
+
Cleaned up some outdated code left in uplinks.dm
+
+
Fox McCloud updated:
+
+
Fixes some mobs not being able to hear sounds
+
Fixes the Master Controller not actually shutting down on round end
+
Adds space ants to the game; leave your food on tables or inside a container to avoid infestation!
+
Fixes bees not properly generating if they have a reagent in them
+
Can break bee boxes
+
Fixes bees breaking things they shouldn't
+
Fixes bees not properly injecting toxin if they lacked a reagent
+
purchased bee boxes are no longer wrenched down by default
+
Adds trick revolver to the syndicate uplink for the clown. Teach those pesky validhunters a lesson!
+
Adds the ability for admins to start a revolver only summon gun version; there's also a suicidal version that makes half the guns summoned real and the other half trick revolvers
+
stabilizing agent gets used up in reactions that utilize it
+
flashbangs spark when they initially go off
+
Fixes mech users being stunned by their own flashbangs
+
Fixes necromantic stone not working properly and other edge cases where you had O2 damage and could become O2 damage immune
+
+
KasparoVy updated:
+
+
Adds Vox-fitted Tajaran veil sprites.
+
Removed stray pixel from Vox-fitted gasmask sprites.
+
Adjusts the Vox-fitted blindfold sprite.
+
+
Kyep updated:
+
+
Blob mobs can definitely no longer be spawned in xenobio.
+
Changed playtime requirements for command jobs. HoS/RD/CE/CMO/AI now require 5h played in their department to be playable. HoP/Captain now require 5h played as a member of the command staff.
+
+
Markolie updated:
+
+
Fixed some issues the compiler doesn't spot and some start up issues.
+
+
Ty-Omaha updated:
+
+
Start now confirmation is now a config option
+
Grid check event sound effect
+
+
farie82 updated:
+
+
Antidrop give edge case fixed
+
Can't give items to resting people now
+
put_in_hands now checks if you actually have hands
+
Wrapping lockers and crates now takes 1.5 seconds to do
+
Welding lockers now takes 1.5 seconds to do
+
+
+
01 April 2019
+
Arkatos updated:
+
+
New Blob UI buttons for Storage Blob and Split consciousness abilities
+
New custom icons for Storage Blob and Split consciousness abilities
+
Added Node Requirement verb to the Blob. This verb, which is activated by default, enforces that resource and factory blob structures are built in a close proximity of the core/node in order to properly function. Players can disable it anytime in the Blob tab.
+
Remove Blob verb now has a new feature - partial refund for special Blob structures. When Blob Overmind removes special blob structure (such as a factory or node), it will receive 30% of the structure cost back as a refund.
+
Blob Overminds now show in Check Antagonists admin verb
+
Blob Mobs now use complementary colors of the Blob Overmind reagent as their own color
+
Removed Dark Matter from a list of possible Blob reagents
+
+
Fox McCloud updated:
+
+
Fixes syndicate medborgs and regular medborgs not having handheld defibs
+
Fixes multi-tile airlocks breaking and not leaving behind an assembly
+
Updates the Timer SS
+
Roundstart ChemMasters are now constructable/deconstructable
+
Can upgrade ChemMasters. Larger beakers mean a larger reservoir
+
Mobs that are gibbed with strange reagent and GBS have a bit more of a dramatic flare to them with violent convulsions before exploding into tiny bits
+
+
Ty-Omaha updated:
+
+
Modified alert sounds for Code Gamma and Code Epsilon.
+
+
dovydas12345 updated:
+
+
Fixes AI's toggle floor bolts ability
+
+
farie82 updated:
+
+
Bluespace golems no longer can crash the server
+
Spontaneous combustion now has a minimum stacksize of 1. No more getting wet from the fire virus
+
+
+
30 March 2019
+
Fox McCloud updated:
+
+
Fixes a runtime involving decapitation
+
playing sounds performs better
+
+
Ty-Omaha updated:
+
+
Removes SSD sleep bubbles from ghosts
+
+
+
29 March 2019
+
Arkatos updated:
+
+
Fixes #11087 - Swarmers are now locked to their default action intent
+
Swarmers are now able to open airlocks and windoors (access restrictions still apply)
+
Added new Wizard item - Bottle of Ooze! This powerful item awakens all-consuming Morph, ready to eat everyone and everything on the station! Be careful though, as Morph diet also includes Wizards.. Costs 1 point in the spellbook.
+
Added custom icon for Bottle of Ooze
+
Morph introduction is now properly formatted
+
Added new Blob UI and icons, ported from /tg/station13
+
Added new *Blob Help* verb, designated to help out new players playing as Blob
+
Added descriptions for each Blob reagent
+
Added complementary colors for each Blob reagent
+
Blob marker now uses complementary color of Blob reagent as it's own color
Crit has been dramatically overhauled. Treating patients now requires a broader range of medicine. Recommend checking out a guide for how to treat using the new system!
+
Medical vendors now have styptic and silver sulfadiazine, saline, atropine, mannitol, mutadone, calomel, diphenhydramine, oculine, insulin, morphine, and potassium iodide for helping treat new patients. Amount of Gauze, Advanced Trauma, and Burn packs has also been increased.
+
Adds new handheld defibs. Utilize these for treating patients with cardiac arrest. Note: these do not revive people from the dead!
+
Doctors lockers now have a handheld defib in addition to a regular defib.
+
Medical borgs now have a handheld defib
+
CPR dramatically buffed. Heavily lowers O2 damage and resets losebreath to 0
+
Cryoxadone tuned down a little
+
Health analyzer UI altered ever so slightly for cardiac arerest, so it's easier to find
Upgraded Robotic Hearts now attempt to correct both cardiac failure and cardiac arrest tweak; Upgraded Robotic Hearts now do not punish you quite as severely for receiving a shock while having one (EMPs will still destroy you though)
+
Corazone recipe removed
+
hotspot sprites updated; fire will also now appear over top of things, rather than underneath it
+
Roundstart chem dispensers are now construcable/deconstrucable and can be moved
+
Energy ratio for chem dispensers increased by x10 (how many reagents you can dispense before running out and how quickly it recharges is all the same, however)
+
Adds the ability to add a single unit of reagent in the chem dispenser
+
Adds the ability to isolate reagents in the chem dispenser
+
Portable chem dispenser removed (the circuit board for them now makes full dispensers)
+
Fixes some suicides dealing damage and gibbing you at the same time
+
Allows you to suicide with more object types. Currently the only new object type you can suicide with is the gibber
+
+
Kyep updated:
+
+
Blob mobs can no longer be spawned in xenobio.
+
Blob mobs spawned by blob cores can no longer have sentience potions used on them, which would allow whoever controls them to kill the blob with no countermeasure.
+
+
Mitchs98 updated:
+
+
Adds in Shrimp & Fish Skewers as well as Cheeseburgers. Shrimp Skewer(Grill): 4 Shrimp(uncooked) + 1 Metal Rod, Fish Skewer(Grill): 2 Salmon Meat + Metal Rod + 10u Flour, Cheese Burger(Microwave): Burger + Cheese Wedge.
+
+
farie82 updated:
+
+
Borgs can now only cuff people with two hands. Just like humanoids
+
You can cuff people with at least one hand now
+
+
ingles98 updated:
+
+
Plasma Golems will now report their suicide acts to the Admins.
+
+
+
25 March 2019
+
Fox McCloud updated:
+
+
Fixes some reagent performance edges cases
+
Fixes chem smoke lagging under some circumstances
+
Fixes smoke not wanting to garbage collect
+
Fixes flares not returning a qdel hint
+
Fixes hotspots being slow to ignite turfs around them
+
Fixes LINDA not conducting temperature through things.
+
+
Mitchs98 updated:
+
+
Chitinous Mass is no longer weaponized lag if examined.
+
+
farie82 updated:
+
+
Diona nymphs are grabbable and punchable again
+
+
+
24 March 2019
+
AffectedArc07 updated:
+
+
Preferences are now in alphabetical order
+
+
AzuleUtama updated:
+
+
Added Syndicate MMI for Roboticist Traitors, priced at 2TC. balance: Removed Syndicate MMI from the traitor surgery duffelbag. Price reduced to 2TC.
+
+
EmanTheAlmighty updated:
+
+
Can no longer offer Gateway Terror Spiders sentience potions. ( They literally exploded if you did, and that could have been used to effortlessly clear out hordes of them. )
+
Using the Shadowling ability "Hatch" as a monkey will change your HUD to be the human one.
+
It is now possible to put a collar on any animal that has gained sentience.
+
+
Fox McCloud updated:
+
+
Pills maximum size increased from 50 to 100
+
Chem Master bottle size increased from 30 to 50
+
Pill bottles can now hold 50 pills instead of 14
+
Pill bottles can no longer hold patches
+
Adds Patch Boxes, which can hold patches, but not pills
+
Can now use a pill bottle or patch box on someone to apply a pill/patch from the bottle/box to a mob. Usual delays will still apply
+
Can down an entire pill bottle at once!
+
Cryostylane and pyrosium reactions now consume 2 of themselves when exposed to oxygen
+
fires, temperature, and hotspots can heat anything that contains reagents
+
Having hot/cold chemicals dumped on you or ingesting them will hurt you. Wear a mask or hat to protect from having someone dump the hot/cold things on you.
+
Chem Heater temperature adjustment tweaked; can no longer set temperature on empty containers.
+
Chem Heater generally heats faster, but cannot be upgraded
+
Chem Heater automatically stops around target temperature
+
Adjusts fire stacks and how they're applied with a few chems. Naplam, Phlogiston, fuel, thermite, and a few others have all received changes. Most direct fire damage removed.
+
Adds phlogiston dust; a safer, cooler burning Phlogiston.
+
Water and Firefighting foam will no longer automagically put out mob based fires; they'll reduce fire stacks (when fire stacks hit 0 they put the mob out)
+
cryostylane puts out mobs instantly
+
Heating fuel can set it off. Be careful when heating it now
+
Increased welding fuel tank size from 1000 to 4000 (wall mounted are still 1000)
+
Sorium and Dark matter now actually throw things
+
Thermite now gets applied to turfs. You'll have to heat the turf up to ignite it. Anything that can heat can now ignite thermite on walls
+
Adds fake hotspots. They don't do anything except set you on fire when you cross into them. Chemistry's pyrotechnics use these, for the most part; anything that causes a fireball that's chemistry related uses these
+
Sorium and Liquid dark matter now have visual effects
+
Fixes chem smoke being on the wrong layer.
+
Adds in unidentified tank filled with an unknown experimental gas in deep space. Find it and experiment!
+
+
Tails2091 updated:
+
+
New emotes to Cats and Corgis.
+
Change directories for some creature sounds to be in the creature sound folder.
+
Two bark sounds, a yelp, and a meow.
+
+
farie82 updated:
+
+
Holo firedoors now update atmos correctly after being destroyed
+
Inflatable walls/doors now update atmos correctly after being destroyed
+
Alien resin walls now update atmos correctly after being destroyed
+
Foamed metal walls now update atmos correctly after being destroyed
+
Pod doors (shouldn't ever happen) now update atmos correctly after being destroyed
+
Mining flaps now update atmos correctly after being destroyed
+
+
+
23 March 2019
+
Arkatos updated:
+
+
Players who enable AntagHUD are now unable to join the round as swarmers
+
Adds a message explaining why Antag-banned players cannot join the round as cortical borer
+
+
Calecute updated:
+
+
South Prison camera now belongs to Prison camera network, thus showind in Prison camera monitor
+
+
Kyep updated:
+
+
Admins offering control of a mob with no real_name to ghosts will no longer cause a "Do you want to play as ?" popup. Instead, the ? will be replaced with a descriptive string, such as "the blobbernaut".
+
+
Tails2091 updated:
+
+
Lockboxes actually close when locked now.
+
+
farie82 updated:
+
+
When disarming a bomb from a guardian you now don't pickup an empty object.
+
no more organ: spam sorry admins
+
+
+
22 March 2019
+
Arkatos updated:
+
+
Updated Tarot Deck description in Wizard's spellbook, credits to /tg/station13
+
+
Fox McCloud updated:
+
+
Smoke now has much better sprites and has a new area of denial behavior
+
+
Mitchs98 updated:
+
+
Fixed Dionae names so "Embrace of Starsong (as Embrace Of Starsong)" will no longer happen when renaming ID's at a ID Console.
+
+
Quantum-M updated:
+
+
Vox Cargo Crate - Contains two vox tanks and two vox masks. Costs 50 cargo points.
+
Plasmaman Cargo Crate - Contains a Orange plasmaman space suit and helmet, along with a breathing mask and a emergency plasmaman tank. Costs 75 cargo points and requires EVA access.
+
+
+
20 March 2019
+
Dave-TH updated:
+
+
Krav Maga gloves can no longer steal the unstealable.
+
+
farie82 updated:
+
+
Fixed the middle mousebutton locking exploit
+
+
+
17 March 2019
+
AffectedArc07 and Alonefromhell updated:
+
+
Cell management consoles: See the status of all brig cells without having to leave your office
It is no longer possible to crawl into a vent while you are simultaneously buckled to a chair or other solid object.
+
+
farie82 updated:
+
+
Adds a confirmation to the start now verb. Make it ansari proof
+
The invisible bumping into something should be fixed now
+
Fixes the atmos bug
+
+
+
16 March 2019
+
Ty-Omaha and Ionward updated:
+
+
Carbon humans (people, not animals) who go SSD will now get ZZZ bubbles to indicate they are SSD
+
+
+
15 March 2019
+
Arkatos updated:
+
+
Fixes #10987 - Guardians can now see the action intent they are on
+
Added custom action intent icons for Guardians
+
+
Couls updated:
+
+
Added a new line to the defib examine text
+
+
+
14 March 2019
+
Couls updated:
+
+
tweaked shesi's fluff sprite
+
+
Quantum-M updated:
+
+
Changes the stamp sprites.
+
Add new sprites for the infernal and employment contracts.
+
Different organ sprites for each species
+
Different MMI sprites based on different species brains.
+
+
+
13 March 2019
+
Couls updated:
+
+
universal translate no longer makes emotes over comms impossible
+
fixed a few typos with simple mobs
+
+
+
12 March 2019
+
Arkatos updated:
+
+
Fixes #10261 - Pure Vampires in Traitor+Vampire gamemode will now properly show in AntagHUD
+
Fixes #9494 - Pure Changelings in Traitor+Changeling gamemode will now properly show in AntagHUD
+
+
+
11 March 2019
+
Couls updated:
+
+
Display if karma gains are enabled or not on round start(instead of just disabled)
+
Fix wrong message when toggling karma
+
+
rb303 updated:
+
+
Fluff scarf for Rb303
+
+
+
10 March 2019
+
AffectedArc07 updated:
+
+
You will now automatically be given admin rights if you connect to your local server
+
Mapmerge has been replaced with mapmerge2
+
Maps are now the TGM format. This means nothing for people who do not make map edits
+
Discord-related verbs are now under "Special Verbs" instead of "OOC"
+
+
Couls updated:
+
+
Toggle karma button in special verbs
+
+
Kyep updated:
+
+
Admins can now flag characters as having an event role, which makes them show up when admins look at the antag list, in admin attack logs, on antaghuds, and on the end-round score screen.
+
+
Tails2091 updated:
+
+
Added missing simple_animal emote help text.
+
+
TheMadTrickster updated:
+
+
added new fixed nice sprites
+
trashed old ugly buggy sprites
+
+
+
08 March 2019
+
AzuleUtama updated:
+
+
Fixed nuke ops cybernetic bundles giving 6 implants rather than 5.
+
Fixed nuke ops cybernetic bundles being delivered in a box that was then delivered inside another box. balance: Nuke ops shotgun ammo bags and cybernetic bundles can no longer be discounted.
+
+
Dave-TH updated:
+
+
Medical smartfridges now accept IV bags.
+
+
Jazz23 updated:
+
+
Golems loose their shell when they switch species
+
Mousedrop applies slime speed/chill potions.
+
+
+
07 March 2019
+
AzuleUtama updated:
+
+
Uplink items now use tooltips for their descriptions.
+
Uplink reformatted slightly.
+
+
Fox McCloud updated:
+
+
His Grace now allows you to toggle on/off binding to your hand
+
Activating his grace is now down by attempting to open it while it's in your hands
+
His Grace now removes slowed status, confusion, and resets shock stage if you're healthy
+
His Grace can now consume all mobs. Mobs consumed are permanently killed
+
His Grace will now neatly package up the inventory of people he consumes
+
+
Triiodine updated:
+
+
changes Neo-Russkiya Lang key to ?
+
+
+
04 March 2019
+
AffectedArc07 updated:
+
+
Fluff item
+
+
Arkatos updated:
+
+
Fixes #10815 - Cloned cultists now retain their Commune ability
+
+
Fox McCloud updated:
+
+
Hopefully fixes weird stack issues. Maybe. Who knows. The World can burn.
+
+
Kyep updated:
+
+
Hardsuits that can already carry RCDs in their suit storage slot can now also carry RPDs in that slot.
+
+
Nicaragua1 updated:
+
+
Genewul Giftskee is less annoying
+
Fixed Griefsky acces and drop
+
+
Triiodine updated:
+
+
Neo-Russkiya Language
+
+
craftxbox updated:
+
+
open button is separated more from previous href
+
+
datlo updated:
+
+
Shuttle hijacking is no longer interrupted by people cuffed, straight jacketed, or locked inside a welded/locked locker or wall locker.
+
Updated hijack's objective description to reflect the change.
+
+
+
03 March 2019
+
Fox McCloud updated:
+
+
Fixes genetic powers always activating when injected
+
Fixes Diona being able to be speedy and irradiate themselves with genetic powers
+
+
+
02 March 2019
+
Dave-TH updated:
+
+
Wall-mounted defib frames. Swipe an appropriate card to lock the defib in place and use it to save lives!
+
IV bags have been refactored and may now accept any chemical. Play around with them a bit!
+
+
Fox McCloud updated:
+
+
Fixes invisible stacks in hands
+
Fixes invisible bluespace crystals
+
+
Kyep updated:
+
+
Fixed cases of some genetics block SE injectors that are spawned at round start (such as the ones that can appear on the Sol Trade ship) not initializing properly, which would cause them to fail to work, and generate a runtime error. refactor: Did some minor refactoring to dna_injector.dm, fixing bad spacing.
+
+
Nicaragua1 updated:
+
+
Bots now drop their proper robotic arm
+
Honkbot drop is consistent with other bots
+
+
datlo updated:
+
+
Added navigation computers to the nuclear, SIT, SST, ERT, and vox shuttles. This computer lets you set a custom destination to jump to.
+
Most off-station shuttle consoles are now indestructible and impossible to deconstruct.
+
Added atmos blocking tiny fans and a security camera console to the ERT shuttle.
+
+
farie82 updated:
+
+
Can't use telepathy now when unconcious or dead
+
+
+
26 February 2019
+
Fox McCloud updated:
+
+
Adds in stable mutagen; a DNA altering compound
+
Having the max allowable number of advanced viruses will no longer confer total and complete disease immunity to *all* future viruses infections
+
Maximum number of advanced viruses you can have in your system at once reduced from 3 to 1
+
Removed stimulant symptom
+
Removed weight gain and weight even symptoms
+
Removed Sensory Destruction symptom
+
Sensory Restoration renamed to Mind Restoration.
+
Mind restoration functions largely the same as Sensory restoration, with a few minor number changes that adjust it downward ever so slighty. It no longer heals toxin or eye damage
+
Vision Restoration renamed to a more appropriate "Sensory Restoration"
+
Capulettium is no longer a perma-stun as long as it's in your system; keeps your paralyzed for the same time as it did previously.
+
Fixes edge case mutagen behavior
+
Adds upgraded cybernetic heart to R&D
+
can now repair robotic organs, outside of the body, with nanopaste
+
+
Kyep updated:
+
+
Pink terror spiders are now called Queens after they evolve.
+
The terror spider major event now has a princess variant, and no longer has a mother variant.
+
White terror spider infestations are now less predictable, more spread out over time, and affected by nutrition and some chems, but also have worse consequences if left completely untreated for a long time.
+
+
PidgeyThePirate updated:
+
+
changed a whole bunch of strings to add a bit more flavor to most reagents in the game (most of these can be found in the spreadsheet).
+
resurrected the old "flavor_strength" value which appears fully functional in testing but has been entirely unused.
+
+
Ralta updated:
+
+
Ian can now wear a CentComm Officer Beret to become Blueshield Ian
+
Sprite added for Blueshield armor to corgi_back.dmi
+
beret_centcom_officer and beret_centcom_officer_navy copied to corgi_head.dmi spritesheet
+
+
UmeFuu updated:
+
+
New recipe for cookies and sugar cookies, new ingredients such as pastry dough, flat pastry dough, unbaked cookies and a new tool called circular cutter (Added to the dinnerware vendor). New chem mix to create a specific type of dough for cookies and pastries.
+
Removed old cookie/sugarcookie recipe
+
added reagents of the cookies (They now actually taste like sugar and chocolate): - sugar = 3 - hot_coco = 5
+Also adjusted the sugar cookies nutriment from 3 to 1, just like chocolate cookies (They're made of the same dough after all) Chocolate bar can now be cutted into pieces/chocolate pile
+
added cookie(pastry) dough, flat cookie(pastry) dough, unbaked cookies/choco and circular cutter sprites. (Disclaimer: The cookie dough and flat cookie dough are edits of the normal doughs, pretty obvious but credits to who sprited them. Same with the tray with the unbaked cookies)
+
+
datlo updated:
+
+
Added a "voice" option to the magic mirror, letting you toggle comic sans/wingdings/swedish/chav
+
Free Golem Ship's interior walls and floors are now fully simulated titanium walls/floors, so they can be deconstructed, built upon, etc. balance: Increased the cost of RND boards for free golems to 2000 mining points (from 1500)
+
Golems can no longer activate robotic brains or have their brain put into an MMI.
+
Replaced one welding fuel tank in the golem ship by a chem master 3000.
+
+
farie82 updated:
+
+
Beepsky now can't insta cuff you when you run away and get back close to him.
+
+
+
24 February 2019
+
Fox McCloud updated:
+
+
Adds the compact syndicate sniper rifle to the uplink. A weaker, low capacity variant of the operative syndicate rifle
+
Fixes blindness mutation not making you blind
+
+
datlo updated:
+
+
Golems can no longer use telescience consoles.
+
Nuclear operatives can now choose to take over a cyborg when spawning one, with a ghost playing the nuclear operative.
+
+
+
23 February 2019
+
datlo updated:
+
+
Golems can no longer be objective targets
+
Offstation antag/special roles such as the ERT, abductors, etc, can no longer be objectives targets
+
Nukies no longer retain flavor text from saved character
+
Antag clowns can now toggle their clumsiness off and on.
+
+
+
19 February 2019
+
Citinited updated:
+
+
Using a multitool on a conveyor switch now switches between one and two directions without needing you to set it on a menu.
+
+
+
17 February 2019
+
Arkatos updated:
+
+
Changed Aurora Caelus event ending title to actually reflect that event is ending
+
+
Nicaragua1 updated:
+
+
Name of secbots
+
Honkbot wasnt dropping oil when exploded
+
+
+
16 February 2019
+
Alonefromhell & AffectedArc07 updated:
+
+
Tweaked the discord link alert text slightly.
+
+
Mitchs98 updated:
+
+
Bar Starter Kit to Cargo. 20 points for both Beer/Soda Boards and a package of glasses.
+
Beer and Soda Machines can now be wrenched to move them.
+
Beer and Soda Machines can now be constructed as well as upgraded to include a slightly wider range of drinks.
+
Properly named the Banana Honk to Banana Honk from Banana Mama.
+
+
Nicaragua1 updated:
+
+
Adds General Griefsky bot and a toy version!
+
Spin-sabre sound
+
Adds Griefsky sprites
+
+
Terilia updated:
+
+
Added the donksoft sniper rifle
+
special donksoft sniper foam darts & special foamforce sniper foam darts
+
Sniper Foam Boxes && Riot Sniper Foam Boxes.
+
creates an admin log, if a player is being hit by a Foam Dart which has been tinkered with.
+
fixes a small misalignment in the magazine sprite if a dart is loaded.
+
+
aleksix updated:
+
+
AI's "Wipe Core" now properly ghosts the player
+
+
farie82 updated:
+
+
Removes some of the chaplain special religion names
+
+
+
15 February 2019
+
aleksix updated:
+
+
posibrains and robobrains don't vanish upon the controlling player's suicide
+
+
+
14 February 2019
+
AzuleUtama updated:
+
+
Added Super Surplus Crates from TG. They contain 125TC worth of gear, but cost 40TC meaning you'll need to team up if you want one.
+
The Surplus chance value for various uplink items will now work when ordering a crate.
+
+
Citinited updated:
+
+
Adds jestosterone to the list of standard reagents, not sure if this has any in-game effect.
+
+
EmanTheAlmighty updated:
+
+
Sentience event now adds some damage to the affected mob.
+
Sentience event now adds health to the affected mob, rather than replacing the old value with another value.
+
+
Mitchs98 updated:
+
+
IV Drip crate can now be opened by general medical personnel, instead of only the CMO.
+
+
TDSSS updated:
+
+
NT rep and Magistrate lose access to the HOP office
+
+
aleksix updated:
+
+
made the lighter size consistent before and after first lighting.
+
+
datlo updated:
+
+
The Nuclear Authentification Disk can no longer be taken from the station by the ERT, Abductors, or Sol Traders.
+
+
+
12 February 2019
+
Citinited updated:
+
+
Fixes some spelling mistakes in the NT soul ownership contract
+
+
Kyep updated:
+
+
Added pink (princess) T3 terror spider, better terror spiderling AI.
+
Tweaked green and mother terror spiders. All terror spider types now have their own variants of the standard spider web.
+
+
datlo updated:
+
+
Added Greey's fluff duffelbag
+
Staff and wand of door can now also open lockers.
+
+
+
11 February 2019
+
AffectedArc07 updated:
+
+
Admins that linked their discord account that round no longer show up as "the adminkey" in adminwho.
+
Changelog button loads properly on darkmode now
+
Added an admin verb that allows admins to forcefully unlink discord accounts
+
+
Fox McCloud updated:
+
+
Cryotubes no longer passively heal patients without chems. Effectiveness at stabilizing critical patients increased
+
Sleepers no longer gain additional chemicals when upgraded. Selection of chemicals altered
+
+
Shadeykins updated:
+
+
Added Chav to roundstart character preferences.
+
Removed Epilepsy, Tourette's, and Can't speak properly from roundstart character preferences.
+
+
datlo updated:
+
+
Reworked golems to use the ghost spawner system. Craft a golem shell with adamantine then apply 10 sheets of minerals to finish it.
+
Added golem subtypes. Each material has pros and sometimes cons. Type depends on the material used during construction.
+
Golems are now more resistant to damage and are no longer slowed by the cold of space.
+
Golems now get golem-y names.
+
Fixed golem's stone face hiding their identity, showing them as unknown.
+
Added the Free Golems mob spawners and ship. Go do whatever.
+
Added a small asteroid on the telecomms zlevel.
+
Added Shesi's fluff winter coat
+
You can no longer use mob spawners (old station/golems) if you've forfeited your right to respawn.
+
+
+
10 February 2019
+
Fox McCloud updated:
+
+
Allows you to switch strap sides on leather satchel
+
+
TDSSS updated:
+
+
New space ruin, the crashed wizard shuttle. Rumored to contain fabulous magical treasures.
+
+
Ty-Omaha updated:
+
+
Reviver implant does not heal when you sleep, only when you fall unconscious involuntarily
+
+
+
09 February 2019
+
AffectedArc07 updated:
+
+
You can now link your discord account and BYOND account together
+
With the accounts linked, you can get roundstart notifications within discord!
+
Fixed roundstart message in discord so that people are notified instead of characters being replaced
+
+
Fox McCloud updated:
+
+
Adds Fox's fluff coat
+
Health HUDs now have a defib indicator showing if they can be revived with a defib or not
+
Defib "safe" time reduced from 5 minutes to 2 minutes
+
fixes a bug where sometimes revived individuals still appeared to be dead or severely damaged on health HUDs after being revived with a defib
+
+
MINIMAN10000 updated:
+
+
Configuration option for disabling subsystems
+
+
Quantum-M updated:
+
+
Headslug sprite looks more deader.
+
+
TDSSS updated:
+
+
Singularities can no longer be pushed
+
+
Triiodine updated:
+
+
ozewse fluff item
+
+
+
08 February 2019
+
Alonefromhell updated:
+
+
Drones should die properly now.
+
+
Kyep updated:
+
+
Characters are no longer massively more/less likely to be chosen for head jobs, especially the Captain job, based on their character's age.
+
+
Shadeykins updated:
+
+
Food descriptions/casing.
+
+
+
07 February 2019
+
Alonefromhell updated:
+
+
Pineapple Salad's fluff coat
+
+
Dovydas12345 updated:
+
+
Fixes cult shackles appearing on the ground when removed
+
+
+
06 February 2019
+
DrunkDwarf updated:
+
+
Reduced the size of the Ward-Takahashi Alt IPC head to prevent pixels clipping when wearing human clothing.
+
+
+
05 February 2019
+
Alonefromhell updated:
+
+
LDM and Sorium should no longer push/pull ghosts
+
+
Kyep updated:
+
+
fixed a "_logging.dm,85: Cannot execute null.simple info line()" runtime when xenobio slimes emoted.
+
+
+
03 February 2019
+
Fox McCloud updated:
+
+
Fixes a few edge cases of being able to create immunity to a few diseases
+
Adds suspiciously Voxy outfit to the game
+
Lack of breathing will render you unable to speak
+
+
MINIMAN10000 updated:
+
+
Boom function now properly checks for fuel
+
+
Tayyyyyyy, TaukaUsanake updated:
+
+
pAI units now have access to a flashlight module, which can be obtained with 5 RAM points.
+
+
+
02 February 2019
+
AzuleUtama updated:
+
+
Added Pack of C-4 for Traitors and Nuke ops. Comes with 5 C-4 charges for 4TC.
+
+
Kyep updated:
+
+
Made playtime numbers displayed to admins (in the playtime report) and players (in the 'check my playtime' verb) clearer in meaning.
+
+
MINIMAN10000 updated:
+
+
Mobs in help intent do not push mobs pulling a structure or the structure they are pulling
+
mobs standing on the same tile when being walked into on help intent.
Mob spawner menu buttons now work. This time it really works, I swear.
+
+
uc_guy updated:
+
+
Non-breathing mobs no longer cause an increase in germ level by not wearing a mask.
+
+
+
01 February 2019
+
AffectedArc07 updated:
+
+
Disabled darkmode is now normal grey, not full white
+
Changelog button now respects darkmode and will update when clicked
+
+
Citinited updated:
+
+
Sexy clown suits now have the squeak component
+
You can now change the way your sexy clown mask looks
+
+
Ty-Omaha updated:
+
+
Admin save feature in build mode will ignore mobs
+
+
datlo updated:
+
+
Wingdings now garbles sentences.
+
Clown and mime now have their ID properly updated to their new name after they rename roundstart
+
Added some ID photo outfits to some jobs missing it.
+
Agent ID photo editing refactored. The photo now looks the same as a real ID, with an outfit based on the job you've forged on the ID.
+
Agent ID should now be impossible to distinguish from a real ID by non-antagonists once properly forged.
+
You can now reset access or delete the agent ID's information without having to do both.
+
+
+
31 January 2019
+
Darkmight9 updated:
+
+
Adds the Camera Flash. A flash disguised as a camera for use as a cheap stun against non-sec, blinding crowds for a get away, and stunning borgs for emaging. Has a charge based system to prevent burning out.
+
Did some changes to flash code allowing different flashes to not be overcharged if one wants to or play a different sound when used.
+
+
Kyep updated:
+
+
Fixed various door control buttons that did not work correctly (brig prison lockdown, admin room lockdown, terror spider away mission containment doors, etc). refactor: refactored door_control buttons to check the GLOB.airlocks list, rather than doing a range(huge_number) check.
+
Terror Spider movement speed settings are no longer ignored when under player control. Instead, movement speed has been unified for both AI and player controlled spiders. Under player control, reds will now be slower, and purples will be faster. Under AI control, all spiders will be slower, except reds, which will be faster.
+
+
alffd updated:
+
+
revert to SS13 bot standard.
+
+
datlo updated:
+
+
Fixed surgery bugging and sometimes not starting properly when you try to surgery on a table or roller bed.
+
Surgery can now be done on any type of bed, with penalties.
+
Help intent is now required to start surgery. Was already needed to do surgery steps.
+
Surgery early cautery has been refactored. It is still done by holding a cautery in your inactive hand, but can now be done using ghetto tools, which can fail.
+
Medical cyborgs now have a laser scalpel instead of scalpel and cautery. lt is slightly faster and more versatile than standard tools.
+
Medical cyborgs now have a medical gripper. You can help patients up with it.
+
Medical cyborg can now cauterize incisions early by using the laser scalpel.
+
Added two black suit jackets to the arrivals locker room vendor
+
Added the armored suit jacket to the Bond, Payday, and Professional syndicate bundles.
+
Replaced the X4 in the Payday bundles by a C4.
+
The professional syndicate bundle now gets thermal fake sunglasses instead of thermal fake mesons.
+
Replaced the toolbox in the professional syndicate bundle by a pair of combat gloves.
+
Wingdings mutation works again.
+
+
+
30 January 2019
+
AffectedArc07 & Teri updated:
+
+
There is now a toggle-darkmode verb to switch darkmode on and off
+
Chat settings also has a dark mode
+
The icon for the server is now the paradise palm tree
+
+
Shadeykins updated:
+
+
New Russian statue
+
Moved some cables, swapped a vendor.
+
Fixed missing door button, some dupes, and unintended object behavior.
+
+
Terilia updated:
+
+
Added a notification about the chat reconnecting on toggling of the dark chat mode.
+
+
+
29 January 2019
+
Alonefromhell and Mitchs98 and farie82 updated:
+
+
Cake cat is now makeable.
+
+
Kyep updated:
+
+
Player-controlled hellhounds will no longer activate their smoke attack when they touch people on help intent.
+
Greater hellhounds (a far more dangerous version of the hellhound) now have descriptions that make it clear they are not the same as the regular hellhounds people are used to seeing.
+
+
farie82 updated:
+
+
fixes the viruses symptom creation being bugged. No more bluespace symptom creation
+
+
v0idp updated:
+
+
Discord Bot Functionality
+
+
+
28 January 2019
+
AzuleUtama updated:
+
+
Fixed Binary Key's description to give the correct code to use when communicating with the AI or borgs.
+
+
Ionward updated:
+
+
Ionward's fluff coat
+
+
Shadeykins updated:
+
+
New derelict station. New floortiles (brownfull, cautionfull, darkredgreen, darkredblue, darkredyellow) New trash subtype (spent ammo casings) New titanium walls subtype (nodecon) Minor/oblique lore references (USSP, TSF, Cult/Bluespace) Context/modified objects (custom descriptions, slogans, etc.)
+
Old derelict station, two suspicious toolboxes
+
Remap teleporter, DJ station
+
Clown shuttle missing adjacent wall tiles
+
+
datlo updated:
+
+
Abductors no longer start with your preset character's flavor text.
+
Abductor scientists now have their SE properly cleaned on spawn.
+
+
+
27 January 2019
+
Citinited updated:
+
+
Fixes tape being unapplicable to headsets and the autopsy scanner
+
You can't tape intercoms any more
+
The chemist can now create a new clown-based reagent using banana juice, lube, blood, space drugs, and salt.
+
Jestosterone heals brute damage for clowns, triggers annoying side-effects in other crewmembers, and is toxic to mimes.
+
+
Kyep updated:
+
+
fixed a runtime in hear_say.dm
+
Fixed item_attack / attack_obj runtime.
+
Fixed runtime when double-clicking a stool in-hand.
+
Antag objectives (kill, debrain, etc) can no longer target people on unreachable zlevels, like the admin-only/centcom zlevel.
+
fixed incorrect definitions of some spells related to shapeshifting.
+
Admin JMP links now work even if you're already following someone/something.
+
+
Kyep and alonefromhell and Ty Omaha updated:
+
+
Whispers are now fully readable in admin log.
+
+
TDSSS updated:
+
+
ether in syndie medical borg's hypospray replaced with hydrocodone
+
syndicate medical borg's hypospray no longer incorrectly lists its content
+
+
datlo updated:
+
+
Syndicate medical cyborgs now get a portable full body analyzer, making them much more effective field surgeons.
+
Bat swarm can no longer be spawned by gold slime extracts or reality tears. Regular bats can still be spawned.
+
+
+
26 January 2019
+
AzuleUtama updated:
+
+
C4 and X4 are now much better at destroying objects they are directly placed on.
+
+
Citinited updated:
+
+
Renames the "Bar" on the Centcomm level to "Bar Lounge".
+
+
Shadow-Quill updated:
+
+
The engineering outpost now has atmospheric blocking tinyfans in the mass drivers.
+
Changed the wall in the Kitchen/Botany vendor to a plating.
+
+
datlo updated:
+
+
Fixed bluespace bunny ears fluff item description
+
Chameleon flag reworked : Now cost 1 TC from 7, but starts without an explosive. It can be boobytrapped using any grenade or a syndicate minibomb.
+
Chameleon flag moved from "Explosives" to "Stealthy Tools" in the uplink.
+
Fixed description of syndicate flags on the suspicious supply depot.
+
Books now deal light damage on hit if you're not on help intent. Space law book deals extra damage.
+
+
+
25 January 2019
+
Agameofscones updated:
+
+
Cheeky Crenando's Soviet Greatcoat Fluff item.
+
+
Aurorablade updated:
+
+
Pineapplesalad fluff item
+
+
AzuleUtama updated:
+
+
Damp rags no longer have a lid, and must remain inferior to other containers.
+
+
Jazz23 updated:
+
+
Surgical Arm Menu
+
+
Kyep updated:
+
+
Fixed a mapping error in the brig remap PR.
+
+
blinkdog updated:
+
+
Normalized some paths in the code tree
+
+
datlo updated:
+
+
Reduced the cost of plasteel bomb frame crafting to 3 plasteel sheets (from 10)
+
Added emergency oxygen grenades to atmospherics lockers and the cargo emergency equipment crate.
+
+
warior4356 updated:
+
+
Drills now properly stop when turned off.
+
+
+
23 January 2019
+
AzuleUtama updated:
+
+
Various text and formatting changes to traitor items.
+
+
Dovydas12345 updated:
+
+
Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to grab decks of cards, paperbins, chairs, stools.
+
Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to split stacks of sheets.
+
+
Fox McCloud updated:
+
+
Fixes null crafting recipes
+
+
Ionward updated:
+
+
Updated some drink sprites!
+
+
datlo updated:
+
+
Added sprites for the SST hardsuit (Mostly black with dark red), sprited by Ionward
+
Mapped SST and SIT shuttles on deltastation map.
+
+
iantine updated:
+
+
Lumi's fluff mouse
+
Mice now use their rest sprite when resting
+
+
+
22 January 2019
+
TDSSS updated:
+
+
Suit Storage Units to most places that held hardsuits.
+
Ugly hardsuits on racks
+
reworked engineering slightly, removed the pointless hardsuit holding room.
+
+
Terilia updated:
+
+
Added Cake Cat - allowing the chef to create a living small pet in his kitchen.
+
Fixed frosted donuts, as they were filled with "spinkles" and not "sprinkles"
+
+
+
21 January 2019
+
AzuleUtama updated:
+
+
Backpacks will now give a rough indication as to how much space they have left when examining them.
+
+
Nicaragua1 updated:
+
+
added mining drone sprites
+
sound alert for vampire gamemode
+
clown bot
+
clown box (Its made stamping a piece of cardboard with a clown stamp)
+
"honkbot evil laugh"
+
clown bot and box sprites
+
honkbot sprites
+
+
Spartan6 updated:
+
+
Gives Sol Traders a baton and a cargo cap.
+
+
datlo updated:
+
+
RD, CMO, and CE greys will now properly get a translator implant if they need one.
+
Updated the Syndicate Strike team's gear and ready room. Syndicate commandos will now be wearing reinforced black elite syndicate hardsuits and pack more ammo and supplies.
+
Syndicate commandos no longer start with all access.
+
Fixed some issues and improved the usability of the SIT and SST shuttle blast doors. They can now be reliably used to lockdown your shuttle from NT would-be intruders, and can be opened from inside and outside.
+
Fix accidental revert of the Syndicate Forward Base area name
+
+
+
20 January 2019
+
AzuleUtama updated:
+
+
Fixed bee briefcase going into a negative number of remaining bees when used with less than 5 left.
+
+
Shadow-Quill updated:
+
+
You will no longer smack body scanner consoles when you rotate them.
+
+
datlo updated:
+
+
Fixed deathgasp emote not being called on death
+
Fixed nukies no longer exploding on death
+
+
+
19 January 2019
+
Alonefromhell updated:
+
+
Mulecloset killing machine has been fixed. Mulebots are no longer able to be put into closets.
+
+
Shadow-Quill updated:
+
+
Removed a description that gets overwritten, moved the current one to it's old location.
+
+
+
18 January 2019
+
Alonefromhell updated:
+
+
Revenant and Statue vision mode fixed.
+
+
AzuleUtama updated:
+
+
Added Professional Syndicate Bundle
+
Added Soporific Sniper Rifle. balance: Syndicate Bundles rebalanced to be worth more TC on average.
+
+
Nicaragua1 updated:
+
+
clown and mime locker now have correct acces
+
Golgrubs now run away from mechas being piloted
+
+
Quantum-M updated:
+
+
Medical Head Mirror, two spawn in the white medical clothes closet.
+
+
datlo updated:
+
+
Syndicate will no longer force you to play with the shiny new saboteur borg and instead send you the assault borg you actually ordered
+
+
+
17 January 2019
+
Eschess updated:
+
+
Jetpacks work properly when placed on suit slot
+
+
+
16 January 2019
+
Shadow-Quill updated:
+
+
Fixed a typo for when spiderlings enter vents.
+
+
uc_guy updated:
+
+
The burial suit (needed for the devil game mode) now shows up properly.
+
+
+
15 January 2019
+
Jazz23 updated:
+
+
Bluespace Closet
+
Bluespace closet animations/sprites
+
+
uc_guy updated:
+
+
Actually activates devil friends contract.
+
Adds employment cabinet and codex gigas.
+
+
+
14 January 2019
+
Kyep updated:
+
+
Doubled playtime requirements for command/sec jobs.
+
Starts tracking playtime on a per-department basis as well. E.g: "X hours in the Sec department".
+
Fixes bug which can cause more than 2 traders to spawn during the Sol Trader event.
+
Further improved sol trader event in general.
+
Enabled sol trader event to happen late-round as a randomly chosen event. Can only happen if the alert level is below red.
+
+
Quantum-M updated:
+
+
Magistrate Locker to the code.
+
Magistrate version of the Nanotrasen Navy Suit.
+
Gives the Magistrate a new wig, called Justice wig.
+
Magistrate specific stamp.
+
Adds the NT Rep version of the Nanotrasen Navy Suit (which already existed) to the NT Rep locker.
+
+
datlo updated:
+
+
ED bots no longer arrests you just because you have no ID by default
+
Nuke ops now spawn with their pinpointer.
+
+
+
13 January 2019
+
Aurorablade updated:
+
+
Fluff item for Asmerath. rscadd:Accordions now have inhands
+
+
Shadow-Quill updated:
+
+
Stopped emergency shield generators from magically unbolting themselves when they get turned off.
+
+
Superhats updated:
+
+
Vox, Drask, Diona and Grey can now choose the Neutral gender option.
+
+
datlo updated:
+
+
Nuclear operatives can now select the Saboteur module when picking a cyborg, a modified engineering module designed around stealth and sabotage.
+
Fixed an exploit allowing you to get free syndicate cyborgs.
+
+
lordPidey updated:
+
+
Infernal devils have been seen onboard our spacestations, offering great boons in exchange for your soul.
+
Employees are reminded that their soul already belongs to Nanotrasen. If you have sold your soul in error, a lawyer or head of personnel can help return your soul to Nanotrasen by hitting you with your employment contract.
+
Nanotrasen headquarters will be bluespacing employment contracts into the IA's office filing cabinet when a new arrival reaches the station. It is recommended that the lawyer create copies of some of these for safe keeping.
+
Due to the recent infernal incursions, the station library has been equipped with a Codex Gigas to help research infernal weaknesses. Please note that reading this book may have unintended side effects. Also note, you must spell the devil's name exactly, as there are countless demons with similar names.
+
When a devil dies, if the proper banishment ritual is not performed on it's remains, the devil will revive itself at the cost of some of it's power. The banishment ritual is described in the Codex Gigas.
+
When a demon gains enough souls, It's form will mutate to a more demonic looking form. The Arch-demon form is known to be on par with an ascended shadowling in power.
+
Added Devil agent gamemode, where multiple devils are each trying to buy more souls than the next in line.
+
If you've already sold your soul, you can sell it again to a different devil. You can even go back and forth for INFINITE POWER.
+
+
+
12 January 2019
+
AzuleUtama updated:
+
+
Chef Excellence's Special Sauce uplink description updated to be more accurate.
+
+
Shadow-Quill updated:
+
+
Fixed the QMs PDA supply app not showing the correct cargo shuttle location.
+
Changed the capitalization of CentCom and Station in the supply PDA cartridge.
+
+
datlo updated:
+
+
Nuke ops, ERT, and ayyybductors will now properly lose disabilities on spawn.
+
+
+
10 January 2019
+
Aurorablade updated:
+
+
Cap guns was checking for claiber type 'cap' when the ammo was set to caliber typer 'caps'. Fixed.
+
+
+
09 January 2019
+
Dovydas12345 updated:
+
+
Fixed NT Rep and Blueshield office door buttons not having correct required access
+
+
DrunkDwarf updated:
+
+
Analyzers now show the amount of moles within pipes and tanks
+
+
Fox McCloud updated:
+
+
Fixes glasses not properly masking eye-shine
+
+
datlo updated:
+
+
Added the Staff of Slipping to the wizard spellbook for 1 spell point, sprites by Mithrandalf.
+
Added the wizard clown outfit to the wizard vending machine.
+
Added the magic mirror to the wizard den, letting wizards swap to other species and change their appearance.
+
Added spare plasmaman suit, plasma tank, and vox internals to wizard robes racks for any wizard that wishes to change to these species.
+
Made the snack machine in wizard den free to use. (wizards don't take silly credits as currency)
+
+
+
08 January 2019
+
Alonefromhell updated:
+
+
Added an "All" option to ghost hud vision.
+
+
AzuleUtama updated:
+
+
Renamed and reorganized the ammunition in the uplink to make it easier for Nuclear Operatives to find the right ammo for their gun.
+
+
datlo updated:
+
+
Fixed grey translator translating the entire server.
+
Fixed BSA size checks being reversed, causing the BSA to clip through walls or prevent construction.
+
+
+
07 January 2019
+
Fox McCloud updated:
+
+
Fixes auto-injectors being free parapens
+
+
+
06 January 2019
+
AffectedArc07 updated:
+
+
Emitter reflectors are a thing now
+
+
Alonefromhell updated:
+
+
Dark matter and Sorium blob attacks should no longer affect ghosts and cameras.
+
All heads now have a HUD implant according to their department.
+
+
AzuleUtama updated:
+
+
New cane shotgun assassination shells. These buckshot shells are coated with a mute toxin which will prevent anyone hit either calling for help or screaming in pain.
+
Old cane shotgun assassination darts.
+
Cane shotgun now uses its own internal magazine rather than copying the code for the improvised one. It also now starts with an assassination shell preloaded.
+
+
Citinited updated:
+
+
You can now build snowmen out of 10 snowballs, 2 logs, and a carrot.
+
+
Dovydas12345 updated:
+
+
Added office door buttons, which open the office doors, to CE, HoP, CMO, HoS, RD, BS, NT Rep offices.
+
+
FreeStylaLT updated:
+
+
Christmas!
+
+
Mithrandalf updated:
+
+
Added toy handcuffs
+
+
TDSSS updated:
+
+
Variants of Suit Storage Units that are ID locked
+
SSUs can now be hacked. Old SSU maint panel menu removed.
+
IRC chassis now have titanium cost to produce on top of metal.
+
+
datlo updated:
+
+
Added new, different voice sets to Syndicate, Clown, Mime, and ERT/Dsquad mechs
+
Added voice modification kits to the exosuit fabricator, letting you swap a mech's onboard voice to another.
+
Added visual and audio warnings when your mech is running low on power
+
Added visual warning when your mech is locked by maintenance protocols
+
Capulettium fake death will now actually be convincing, fooling examine, medhud, and health analysers, but not body scanners.
+
Capulettium plus can now be used to manually fake your own death when you wish by resting, and wake up when you wish by toggling rest again.
+
Added fake death pill bottle to maintenance loot, contains 3 pills of capulettium plus.
+
Fixed a mech runtime when an empty mech used power.
+
Grey wingdings is now a disability, add it to your saved characters if you want to have them on.
+
Grey translator implant preference added. Translates speech to be comprehensible, the implant can be turned off and on at will.
+
Mutadone no longer removes genes that you have at round start, from your job, species, or disability you've picked in character creation.
+
Mutadone no longer removes powers gained from a completed DNA vault.
+
Removed syndicate uplink management consoles.
+
Nuclear ops now automatically get bonus TC from round start and war declaration split between their uplinks.
+
Nuke ops can now buy stacks of 50 TCs.
+
Added a regular internals box to the Honk Brand Infiltration Kit.
+
CC officers plasmamen now get an appropriate suit.
+
Updated admin-outfitted syndicates
+
Wizard forcewalls can now be walked through by the wizard summoning them.
+
Added a new spell to the wizard spellbook, "Greater Force Wall". Summons a larger wall than the regular one, but requires wizard robes.
+
Added one box of pill bottles to Scichem
+
Replaces one of the two crew monitor consoles in medical front desk by a medical record console.
+
+
improvedname updated:
+
+
Mindshield implant, is now shown by a green flashing outline of your job hud
+
Moves some huds around to make them not overlap
+
changes some icons
+
fixes two missing pixels on execute status
+
+
uc_guy updated:
+
+
Fixes active deswords being pocketable.
+
+
+
31 December 2018
+
Aurorablade updated:
+
+
Fixes Slaughter demons not releaseing corpses on death.
+
Fixes tears in spacetime just kinda sitting there.
+
+
Citinited updated:
+
+
Air pumps will now switch off when the inserted tank is removed.
+
+
Shadow-Quill updated:
+
+
No longer get debug messages from Slaughter Demons dropping mobs on death
+
Removed a useless comment in chronosuit code.
+
+
datlo updated:
+
+
Mech flashbang, banana, and mousetrap launchers now properly throw the item at your target instead of dropping it at the mech's feet.
+
Fixed nuclear operatives burning/choking on spawn if your set character is a plasmaman/vox. (they get healed once the round is done setting up)
+
+
farie82 updated:
+
+
Changed the laser tag gun pathing in the code.
+
Removed the / from the encryptionkey object in code.
+
Fixes the runtime in admin tickets
+
+
uc_guy updated:
+
+
Fixed death alarms / cell timer / beepsky radios.
+
+
+
30 December 2018
+
datlo updated:
+
+
Glowsticks now process fuel properly
+
+
+
29 December 2018
+
Alonefromhell updated:
+
+
Glowsticks are now compatible with shadowlings.
+
+
Spartan updated:
+
+
Adds emergency glowsticks to emergency box. sound: Glowsticks and flares now make more relevant usage sounds.
+
+
farie82 updated:
+
+
at the end of a radiation storm the maint access doesn't get revoked if it was set to emergency before hand.
+
+
+
28 December 2018
+
AzuleUtama updated:
+
+
"Grenades and Explosives" category added to the uplink. Anything classed as such in the uplink has been moved here for easier access.
+
+
Ionward updated:
+
+
missing drask crusader helm #10486
+
+
Kyep updated:
+
+
Added kangaroo, a new creature type that is initially passive, but can be dangerous if provoked.
+
+
Mitchs98 updated:
+
+
All movement / pull resistance has been moved over to tg's move resist system.
+
You now drop a pull by ctrl + clicking anywhere else on the screen, rather than the object/mob being pulled.
+
All atom movables now have move force and move resist, and pull force An atom can only pull another atom if its pull force is stronger than that atom's move resist.
+
Mobs with a higher move force than an atom's move resist will automatically try to force the atom out of its way. This might not always work, depending on how snowflakey code is.
+
As of right now, everything has a move force, pull force, and resist of 1000. Structures can be crushed with sufficiently big move_force.
+
Failing to move onto a tile will now still bump up your last move timer. However, successfully pushing something out of your way will result in you automatically moving into where it was. Makes moving much smoother.
+
Mobs that shouldn't be able to pull objects now use a better check to prevent it.
+
+
Spartan updated:
+
+
ERT Medics now spawn with a medical analyser upgrade.
+
Amber ERT now spawn with a flashlight.
+
Red Engineer ERT now have an Elite ERT Hardsuit.
+
Paranormal ERT now spawn with a seclite.
+
CE toolbelt renamed. grammar: Surgery Belt > surgery belt
+
+
TDSSS updated:
+
+
clumsy people are now properly bad at handcuffing
+
Holoparasites/Guardians using the say verb now use host communication
+
+
Tails2091 updated:
+
+
Mice can *squeak now.
+
+
datlo updated:
+
+
Added the ability for command to set emergency access on all station airlocks with the keycard authentification device. (ID swiper)
+
Added the Boots of Gripping to the wizard hardsuit, sprited by Ionward
+
Fixed a cast check missing plasmaman wiz suit, causing issues with spell icons for them
+
+
improvedname updated:
+
+
Syndi emergency box to nuclear opratives.
+
Moves the suicide pill to the emergency box
+
Adds a recipe for the toolbox to make it a suspicous toolbox
+
+
name here updated:
+
+
new hat in the autodrobe
+
+
uraniummeltdown updated:
+
+
RPDs should be available in hacked autolathes again
+
+
v0idp updated:
+
+
missiles shot from missile racks in mechs will no longer spin in air
+
banana cake and slice
+
+
+
26 December 2018
+
Shadow-Quill updated:
+
+
Fixed being able to start multiple prayers using the prayer beads.
+
+
v0idp updated:
+
+
Syndicate officer will not show in card modification/identification consoles anymore
+
+
+
25 December 2018
+
Ranged updated:
+
+
Mutadone removes dizziness immediately instead of taking 5 minutes
+
+
Ty-Omaha updated:
+
+
Fixes "makes frantic gestures" invalid emote with mute people using spells
+
+
improvedname updated:
+
+
fixed a typo
+
+
v0idp updated:
+
+
no bork in swedish accent while muzzled anymore
+
+
+
24 December 2018
+
Alffd updated:
+
+
Removed fart based mechanics.
+
+
Ty-Omaha updated:
+
+
Removes "name here" from PR template
+
+
datlo updated:
+
+
Added the grenadier belt for nukies, ported from tg, containing a LOT of various grenades to throw at people.
+
Added the gluon grenade (Freeze floors and irradiate) and the frag grenade.
+
Added Toxins tech to RND. Can only be improved by testing explosives in the toxins lab, and unlocks various atmospherics tanks and items in the protolathe.
+
Added the Bluespace Rapid Pipe Dispenser, allowing you to place pipes at a distance. Built in the protolathe after improving Toxins and Bluespace tech. Sprite made by Ionward.
+
Welding Gas Mask now requires toxins tech.
+
Syndicate Officer job now available for admins, along with a brand new office connecting to the SIT, SST, and nuke ops ready room.
+
Remapped SIT and SST starting areas to be next to nuke ops starting area. Added sleepers and a couple of other QOL stuff in their ready rooms
+
Added a holding cell to the SIT starting area
+
Added a teleporter available to SIT and SST if admin enables it, can go to and from the z2 area.
+
Added an armory SST can get if admin enables it. 2 bulldogs, 2 SMG, 1 sniper, 1 medigun, 1 rocket launcher and assorted ammo.
+
Added 3 dark gygaxes, tools, and welding fuel to the SST mechbay room (admin access required)
+
Added a new subtype of mech rechargers for CC zlevel that will always recharge an attached mech even without power/recharger monitor
+
Added SIT shuttle transit area
+
+
v0idp updated:
+
+
Syndicate Officer won't show in nt recruitment anymore
+
+
+
19 December 2018
+
Citinited updated:
+
+
Fixes a bug preventing snow machine crates from being orderable at roundstart. Ho ho ho!
+
+
uc_guy updated:
+
+
Fixed anomalies being disabled by random radio traffic.
+
+
+
18 December 2018
+
Citinited updated:
+
+
Adds the snow machine. Fill it up with water, turn it on, and watch it create a winter wonderland all on its own! For best results set your room's air alarm to the lowest value it can go to.
+
The snow machine is orderable from cargo during Christmas time.
+
You can use a shovel to clear away generated snow. Scrooge.
+
+
FreeStylaLT updated:
+
+
Christmas!
+
+
Ionward updated:
+
+
updated santa hat sprite, use hat to toggle beard
+
+
Tails2091 updated:
+
+
Fixes vent crawl vision sticking around for simple_animals.
+
+
datlo updated:
+
+
Added a global cap on printing papers.
+
+
+
17 December 2018
+
MarsM0nd updated:
+
+
Restores mech radial menu functionality.
+
+
+
15 December 2018
+
MarsM0nd updated:
+
+
radial menu now works for normally implanted implants
+
+
datlo updated:
+
+
Added sprites to specie specific boxes made by shazbot
+
+
uraniummeltdown updated:
+
+
Me button added to chatbar
+
+
+
13 December 2018
+
Breenland updated:
+
+
Adds drask ability to have auto-accent.
+
+
Edefff updated:
+
+
increase rollie smoketime to accommodate new chem volume
+
+
Kyep updated:
+
+
Tweaked the syndicate depot to fix various bugs and unintended design things, as well as make some changes to improve fun value.
+
Computer and machine frames are no longer invincible, and can now be destroyed by hostile NPCs.
+
+
McDonald072 updated:
+
+
Fixed being unable to cast lightning with the action button.
+
+
Mitchs98 updated:
+
+
Add's Makiroll's! Larger sliceable variants of sushi that yield four rolls of sushi in the same time that it previously took for one. You can also eat the Makiroll itself for 4x the nutriment/protein of a regular roll of sushi. Requires the Sushi Mat to craft.
+
Add's the Sushi Mat. 3 start in the chef's vendor. New ones craftable with 5 wood and 5 cable coil.
+
+
Shadow-Quill updated:
+
+
Makes people who are miming/mute give a visible indicator of their communion.
+
+
Tails2091 updated:
+
+
trimmed 300ms delay from smash.ogg
+
+
datlo updated:
+
+
Removed access requirement on emagged fax machines
+
+
+
12 December 2018
+
Kyep updated:
+
+
Fixed a few things that should not be possible with pAIs and AIs.
+
+
Tayyyyyyy updated:
+
+
Read only sec hud for IAA and blueshield
+
+
name here updated:
+
+
Fixed Bulldog and C20 having their ammo alarms only go off once per gun.
+
+
+
11 December 2018
+
Alonefromhell updated:
+
+
Miniature energy gun now has an action icon for it's light toggle(like flashlight).
+
+
Azule Utama updated:
+
+
Syndicate Uplink now uses expandable and collapsible categories. General layout of the uplink has also been changed to work alongside this.
+
+
Birdtalon updated:
+
+
Species specific starting boxes.
+
+
Citinited updated:
+
+
Fixes a runtime caused by AIs watching dance machines
+
You can now tape much more than just paper!
+
You can now order a crate full of sticky tape
+
Maximum amount in a tape roll is now 25 (up from 10).
+
Fixes some issues and runtimes in floorcluwne code.
+
Admins will now be informed of a new floorcluwne's chosen target if one is provided via the event.
+
There's a button next to secure storage's blast doors now.
+
+
Darkmight9 updated:
+
+
Added overheal to nanopaste
+
+
Ionward updated:
+
+
fixed slight spriting errors
+
added some more grey headwear
+
+
Kyep updated:
+
+
Fixed runtime related to chaplains.
+
Player-controlled giant spiders will no longer unintentionally poison anyone they nuzzle on help intent. They can still poison people they bite.
+
Altered the warning you get when you try to put one bag of holding inside another, so it is absolutely clear what this does, and there is no chance someone can do so by accident.
+
+
MarsM0nd updated:
+
+
Arm implants use radial menues where suitable
+
Item actions can have icons different from the icon of the item
+
+
MrKicker updated:
+
+
Sorting of call list for holopads
+
+
Shadow-Quill updated:
+
+
Makes the chem-master update it's icon on power change, as well as showing the correct sprite after being loaded in.
+
Changed Oldstation Air Alarms/APCs to no longer give warnings to the main station.
+
+
TDSSS updated:
+
+
ghost spawn menu jump and spawn buttons now work.
+
+
Tails2091 updated:
+
+
Fixed typo for Schrodinger's cat.
+
+
datlo updated:
+
+
Display case burglar alarm no longer triggered if there's no power to equipment
+
+
gangelwaefre updated:
+
+
Aesthetic changes to Lumi's custom sprites
+
+
+
10 December 2018
+
Farie82 updated:
+
+
Can't become 1 pixel big anymore due to genetics
+
+
+
06 December 2018
+
Shadow-Quill updated:
+
+
Fixed protocol spelling in the Photon Projector description.
+
+
TDSSS updated:
+
+
Reverted holopad sorting to make holopads work again.
+
+
+
01 December 2018
+
Kyep updated:
+
+
Fixed a couple of bugs with the special event pets triggered by admin bless command.
+
+
TDSSS updated:
+
+
Ancient Station asteroids now contain minerals and can be mined.
+
+
datlo updated:
+
+
Added 3 carrot seed packets to perma.
+
+
+
30 November 2018
+
Azule Utama updated:
+
+
Fixed an ORM exploit which would let you smelt invalid stacks of alloys.
+
+
TDSSS updated:
+
+
Removed ballgag and assless chaps
+
+
+
29 November 2018
+
Kyep updated:
+
+
Updated chaplains. They now spawn with their nullrod in their hand, and their soulstone in their locker. They now have the ability to bless other players. The more players they bless, the more likely admins are to answer their prayers. There are no longer any atheist chaplains. The chaplain items that reference atheism have been tweaked accordingly, e.g the atheist fedora is now the binary fedora. A few other items have also been tweaked. Paranormal ERT members now count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful version of the nullrod, so they have a reason to use a weapon other than their gun.
+
+
TDSSS updated:
+
+
No more making infinite meat and crashing the server with gibbers
+
+
+
28 November 2018
+
Kyep and FoS updated:
+
+
Updated hellhound with new sprites by FoS, slightly better AI, and more fixes/tweaks.
+
+
MrKicker updated:
+
+
Sort callable holopads by name
+
+
tigercat2000 updated:
+
+
You can now speak in multiple languages in the same message! This works for all forms of speech, including radios. Minus megaphones because fuck em.
+
Some mild formatting errors and inconsistencies that have historically been present within mob speech.
+
Holopads behaving a bit weirdly with how they interact with the typical say system
+
+
+
27 November 2018
+
Azule Utama updated:
+
+
Power beacon made purchasable again in Nuke Ops uplinks.
+
+
Dovydas12345 updated:
+
+
Fixes being able to attach IV drips when incapacitated
+
+
Farie82 updated:
+
+
You can now actually make the rescue jaws
+
+
+
26 November 2018
+
Citinited updated:
+
+
Adds the rubbish bin in front of the kitchen again
+
+
TDSSS updated:
+
+
Medbay secondary storage is now accessible to everyone with medbay access, hardsuits were put behind a windoor with CMO access to keep them at the same level of accessability.
+
Added and removed some items from medbay secondary storage.
+
Medical storage and secondary storage were renamed to be more accurate.
+
+
datlo updated:
+
+
Updated description of finger gun to point out you can holster the gun manually by using it in hand.
+
Fixed a bug where you couldn't learn finger gun if you already knew fake finger gun.
+
Power beacon cost reduced to 10 TC, and is now hijack-exclusive.
+
Guillotines can now be deconstructed with a welder.
+
+
+
25 November 2018
+
Azule Utama updated:
+
+
Job-specific gear can no longer be discounted.
+
Discounted items now get an alternate log entry stating the item's new price.
+
+
KasparoVy updated:
+
+
Fixes Unathi Snout 2 not using the correct sprite.
+
Fixes Unathi Points Head not using the correct sprite.
+
Fixes Unathi Sharp Tiger Head and Face not using the correct sprite.
+
Fixes Unathi Tiger Head and Face not using the correct sprite.
+
Removes Unathi Sharp Points Head and enables Unathi Points Head marking for use on all Unathi head types.
+
+
MarsM0nd updated:
+
+
Coins will now always show a side on being spawned.
+
+
Reagent Scanner Changes updated:
+
+
Removed Mass Spectrometer and Advanced Mass Spectrometer
+
Reagent Scanner and Advanced Reagent Scanners can now identify blood types
+
+
datlo updated:
+
+
Added the Advanced Mimery Series to Syndicate Mime uplink.
+
Added a fake Finger Gun manual to the arcade prize machine.
+
Changed the look of the teleporter hallway from maintenance to dirty hallway.
+
+
+
24 November 2018
+
Azule Utama updated:
+
+
Added uplink discounts. Traitor and Nuclear Operative uplinks now have a discounted gear section! 3 random items will be chosen to be 50% off (rounded down), 25% if they usually cost 20 or more TC. You can only buy a discounted item once per uplink. Ported from TG.
+
+
Eschess updated:
+
+
hardsuit helmets now unlink from the hardsuits upon being detached
+
syndicate hardsuit helmet combat mode can no longer be toggled on hand
Space ruin/gateway hardsuits now should all come with helmets
+
Telecom setup in wizard gateway can now be completed with the present stock parts.
+
+
Ty-Omaha updated:
+
+
Added reflective blobs, these blobs have a high chance to deflect energy projectiles while being vulnerable to ballistics and brute damage. Reflective blobs can be obtained by upgrading a shield blob.
+
+
tigercat2000 updated:
+
+
Fancier Transpara-corner Nano take 2.
+
Nano's build-watching works on 512 again.
+
Nano scrolling issues with the power monitor (they existed before I touched this goddamnit I swear!!!)
+
Rewrote Nano's buildscripts and upgraded all the dependencies (again)
+
+
+
23 November 2018
+
Azule Utama updated:
+
+
Additional check added to damage falloff code, will only delete bullets that reach 0 damage if they actually have a falloff value.
+
+
Kyep updated:
+
+
Dead mice no longer squeak.
+
Ghosts walking over living mice no longer makes them squeak.
+
+
TDSSS updated:
+
+
no more runtime spam each time a simple mob is attacked
+
+
datlo updated:
+
+
Replaced "illegal" and "weapon" in strange objects name
+
+
+
22 November 2018
+
AlAtEX updated:
+
+
re-adds sprites for boxes that disappeared
+
+
AlAtEx updated:
+
+
Added a new medkit for IPCs
+
added a purple medkit
+
Added a repair kit box to start with for IPC's
+
Re-added the crowbar and extended tank to miner's boxes
+
added three new box images
+
+
Azule Utama updated:
+
+
Made laser tag guns work again.
+
Syndicate Cigarettes added to maintenance loot.
+
+
Eschess updated:
+
+
Adds ui button to toggle hardsuit helmet
+
syndicate hardsuit combat mode is activated only by the helmet button
+
+
Kyep updated:
+
+
Added hellhound, a dangerous new monster.
+
+
datlo updated:
+
+
Added the CQC manual to nuke ops and traitor uplinks, letting them remember some of the basics of CQC.
+
+
+
21 November 2018
+
MrKicker updated:
+
+
Added generated sound files to sound/vox_fem , then added references to them in vox_sounds.dm
+
+
+
20 November 2018
+
AffectedArc07 updated:
+
+
NTTC now has multiple job tag styles
+
NTTC now has option to make job tags colored
+
NTTC now has option to make nametags colored
+
NTTC now has options to make command members louder (bold)
+
The NTTC window title is no longer NTSL.
+
+
Azule Utama updated:
+
+
Fixed chameleon suit having two invalid options.
+
+
TDSSS updated:
+
+
Silencers now have a tech origin, give research levels when deconstructed
+
Moved gun attachments to their own folder, code-wise.
+
+
name here updated:
+
+
Fixed a runtime in a syndieteam radio.
+
+
tigercat2000 updated:
+
+
Nano scrolling is 95% less buggy
+
NanoUI's Fancy Mode now less broken as hell remove: 512 support for Nano dev tools
+
+
+
19 November 2018
+
Birdtalon updated:
+
+
Fixes a runtime in safe.dm
+
+
Citinited updated:
+
+
Alt-clicking a jumpsuit removes accessories from it
+
Removing an accessory now shows a small message
+
+
KasparoVy updated:
+
+
Brings the logging of plasma statue ignition up to the same spec at as welder tank explosions.
+
You can no longer ignite plasma statues with disablers.
+
+
Kyep updated:
+
+
Tweaked many of the special admin outfits. This means centcom officers are less likely to be seen wielding illegal syndicate gear, and subtle flaws with many other outfits (such as pirates lacking radio, singulo knights lacking a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) have been addressed.
+
Added several new admin options for fax responses, blessings, and smiting.
+
+
Quantum-M updated:
+
+
Sleeping carp uplink description now points out that it is unable to be learned by vampires or changelings.
+
Holoparasite kit uplink description now points out that it doesn't work on vampires or changelings.
+
Attempting to learn sleeping carp as a changeling or vampire gives you a red warning message.
+
You can now refund the sleeping carp scroll to the uplink.
+
+
TDSSS updated:
+
+
A warning if slings are very close to ascension, so the crew can potentially still stop them
+
+
craftxbox updated:
+
+
add observer/incapacitated check for all sec/medhud actions
+
+
datlo updated:
+
+
Added antag alert sounds that play at roundstart for most major antagonists, ported from TG.
+
+
+
17 November 2018
+
uc_guy updated:
+
+
Syndicate borgs are no longer pseudonymous on syndie radio.
+
+
+
16 November 2018
+
Azule Utama updated:
+
+
Changed falloff damage to be usable on any desired projectile rather than just shotgun pellets. balance: X-ray lasers now use 100 charge per shot (previously 50). balance: X-ray laser guns now have falloff damage. The longer the laser is in the air, the lower its damage becomes.
+
Slight addition to X-ray laser's description.
+
+
Certhic updated:
+
+
Replaces radio freq magic numbers with constants
+
+
Farie82 updated:
+
+
Borgs can't get perma stunned anymore by goliaths and slings and such
+
+
Fethas updated:
+
+
The floors are not safe! HONK!
+
+
Jazz23 updated:
+
+
Added flasher buttons in perma brig as well as windoors in botany, the wardens office, and cargo. Also added blast doors to transit tube.
+
HoP's flasher button not working, CE's secure shutter button and transit tube lockdown button not working.
+
+
Kyep updated:
+
+
The admin verb to list SSD players now highlights players who are another player's antag target. Additionally it lets you despawn players whose body is already in cryo.
+
Fixed a bug which caused banning to fail in rare situations.
+
+
Mitchs98 updated:
+
+
You can no longer rip the hood part of a hoodie off of someone's head.
+
Bee Costume and Monk Robe icons now show up properly in your inventory.
+
+
Triiodine updated:
+
+
Hotfixes taser projectiles being borked due to X-Ray re-work.
+
+
tigercat2000 updated:
+
+
SPEEEEEEEED to the asset cache, making preloaded UI assets transfer much faster.
+
NTTC deserializing works again
+
NTTC regex works again
+
NTTC no longer spams admins
+
NTSL2 no more, it is officially NTTC
+
NanoUI's fancy mode is hot shit again!
+
NanoUI's fancy mode is no longer broken as hell!
+
512 support for Nano dev tools
+
+
+
15 November 2018
+
Azule Utama updated:
+
+
Fixed an exploit which allowed cultists to curse the shuttle more than twice. Steve can only take so much punishment ya know...
+
+
Certhic updated:
+
+
The scrollbar of NanoUI now looks more Nano-ish
+
The title bar of NanoUI now sticks while scrolling
+
changed the mouse hover behavior on the fancy NanoUI buttons
+
+
Dave-TH updated:
+
+
Internal bleeding is now represented by coughing (And occasionally vomiting) blood! Nifty!
+
+
uc_guy updated:
+
+
Fixed the passive effects of prayer beads and prayer bread.
+
+
+
14 November 2018
+
KasparoVy updated:
+
+
Vulpkanin Earfluff can be selected in facial hair again.
+
Vulpine Fluff and Earfluff head accessories and facial hair now have correct icon states.
+
+
uc_guy updated:
+
+
Borgs no longer have infinite roller beds.
+
+
+
13 November 2018
+
Birdtalon updated:
+
+
Fixes playtime self checker.
+
+
Certhic updated:
+
+
fixed a cigs runtime error
+
+
TDSSS updated:
+
+
Ancient station's lockdown is now lifted correctly.
+
Ancient station RD console can now be used.
+
+
craftxbox updated:
+
+
use mob voice instead of mob name for radios broadcasting signals.
+
+
datlo updated:
+
+
Prevent wizards from casting rod form inside the wizard den.
+
+
+
12 November 2018
+
Azule Utama updated:
+
+
Fixed text errors in the descriptions for Booger cocktails and Feral cat grenades.
+
+
Birdtalon updated:
+
+
Verb to check your own playtime.
+
+
CornMyCob updated:
+
+
You can now unwrench and move the library machines/computers, chem master, chem heater, washing machine, pandemic and PDA painter
+
+
Farie82 updated:
+
+
Added the pressure damage reduction to mining bots. No more killing machines called mining bots.
+
+
variableundefined updated:
+
+
AI can now select the alien screen display
+
Nearly every single sprite accessories (species customization option) has been separated and refactored. Report missing hairstyle / screen / horns / frills / tails etc.
+
Desolate's peacekeeper fluff cyborg sprite is now his service sprite.
+
+
+
11 November 2018
+
Azule Utama updated:
+
+
Borgs can no longer stunbaton into infinity. Their batons will now deactivate if they have no power left after hitting someone and cannot be turned back on until they recharge.
+
+
Eschess updated:
+
+
large cardboard boxes now show their size when examining
+
fulltile plasma glass windows now have armor
+
rised plastitanium windows integrity
+
+
Farie82 updated:
+
+
You can now hurt mining bots with welders on any attempt other than help
+
Can put suits and such back into the suit storage units
+
Fixed the tank/magboots storage part being called Breathmask storage, lazy copy pasta
+
+
Squirgenheimer updated:
+
+
Hatched alien larvas will default to being created on the turf of the mob instead of the mob's location, unless specifically allowed (like closets and spacepods)
+
+
tigercat2000 updated:
+
+
Ears are now an organ, which can be damaged, removed, and inserted!
+
Human icon code should perform massively better.
+
+
+
10 November 2018
+
Citinited updated:
+
+
Prevents an infinite metal exploit using the autolathe.
+
Minimum returnable metal of ammunition boxes has been lowered from 2000 to 500.
+
+
Dovydas12345 updated:
+
+
Fixes being unable to slice certain food grown by hydroponics (pineapple, watermelon etc.)
+
+
Shazbot updated:
+
+
Some fancy new box sprites, props to Shazbot for the sprites
+
Old cuff box is gone
+
+
TDSSS updated:
+
+
Quarantine is now its own lawset.
+
+
+
09 November 2018
+
Alonefromhell updated:
+
+
Most sheets held in hand should now display either a metal or reinforced glass icon where appropriate.
+
Holopad should no longer automatically revert to default sprite.
+
+
Azule Utama updated:
+
+
Small change to cursed heart's spellbook description.
+
+
AzuleUtama updated:
+
+
RCD now gives visible messages when building without enough ammo or on an invalid tile.
+
+
Citinited updated:
+
+
Fixes ghosts being able to make conveyors drain more power than they should.
+
+
Dave-TH updated:
+
+
Space levels is named now.
+
+
Mitchs98 updated:
+
+
Chemical implants now work and can be properly filled via beaker or syringe. Reagents inside can also be syringed out.
Added drill and safe intenral sprites made by Shazbot194
+
+
+
08 November 2018
+
Citinited updated:
+
+
Conveyors use less power now
+
+
Eschess updated:
+
+
fixes the NOR, NAND and XOR logical gates
+
reinforced plasma glass windows give you reinforced plasma glass sheets now
+
fulltile reinforced plasma glass windows now have armor
+
+
Farie82 updated:
+
+
Mining bots now function as expected when giving them a health upgrade. No more repairing without healing
+
+
Fel updated:
+
+
You can now craft wooden barrels with 30 pieces of wood! They can hold up to 300u of reagents.
+
Putting hydroponics-grown plants into the barrel lets you ferment them for alcohol! Some give bar drinks, while others simply give plain fruit wine.
+
Reagent containers like bottle & glass should be more consistent now.
+
+
Spartan updated:
+
+
Plastic bags and wet floor signs can now spawn in maint.
+
Plastic bags are now supplied to your syndicate uplink. Apply directly to head.
+
+
Wario4356 updated:
+
+
Mecha can now drill other mecha
+
+
Warior4356 updated:
+
+
Mecha drills now tell you when they can't drill
+
+
datlo updated:
+
+
Added the Toxins Payload Casing to crafting recipes, a new method of activating tank transfer valve bombs.
+
+
tigercat2000 updated:
+
+
Mecha now use action buttons instead of ugly verbs.
+
Mecha weapons can now be selected through a radial menu brought up by Ctrl Clicking on the Mecha while you are piloting it.
+
Tooltips now appear on radial menu buttons when you hover over them. Seriously, why wasn't this a thing in the first place?
+
Action button icons are now located in their own file.
+
Captain and HoS can be nearsighted again.
+
+
variableundefined updated:
+
+
Baycard, including tarot cards to loadout
+
Baycard to prize machine
+
All non-syndicate card deck on map has been replaced with bay card.
+
+
+
07 November 2018
+
Spartan updated:
+
+
Bluespace Crystals no longer use the entire stack when used on self to teleport.
+
+
Squirgenheimer updated:
+
+
toggling off global antag candidacy will disable you from being selected by the Create Antagonist verb.
+
+
TDSSS updated:
+
+
added mulebot control to captain's PDA again.
+
+
name here updated:
+
+
objective lists are now sorted for admins.
+
+
uc_guy updated:
+
+
IPCs and slimes now have an effect on the floor when bleeding.
+
+
+
06 November 2018
+
R1f73r updated:
+
+
Added a death text to headslugs when they die
+
+
Squirgenheimer updated:
+
+
blob and autotraitor game modes will now check for Global Antag Candidacy when picking new antagonists after round start
+
Global Antag Candidacy button will now show up after round start
+
+
TDSSS updated:
+
+
Can no longer attempt to build tranquilite walls (and delete the wall in the process)
+
+
TatsumakiMagi updated:
+
+
target icon updates when lit by user
+
+
Triiodine updated:
+
+
Airlock sensors & vent system to west mining outpost (Safety first!)
+
Disposals inlet now directly goes to cargo _delivery_ (not conveyor)
+
More spawns for science nerds in accordance to highpop.
+
All conflicting C_tags, dispatch cops or AI should freely use all cameras now.
+
[delta] APC to virology mainroom
+
[delta] All unsimulated turfs are now simulated.
+
+
Ty-Omaha updated:
+
+
Fixes spacing in admin deletion logs
+
+
datlo updated:
+
+
Added syndicate themed internals to traitor spacesuit and hardsuit.
+
+
+
05 November 2018
+
AzuleUtama updated:
+
+
Added Traitor's toolbelt
+
Replaced Military belt with Traitor's toolbelt in the uplink.
+
Price of new belt lowered to 2TC
+
Replaced Military belt with Traitor's toolbelt in maintenance loot.
+
+
Regen updated:
+
+
The tentacle changeling power now generates admin logs.
+
+
TatsumakiMagi updated:
+
+
Fixes adjacency and standing checks for cutouts
+
+
+
04 November 2018
+
AffectedArc07 updated:
+
+
Makes status display font crispy. mmmmmmmmmmmmm
+
+
Citinited updated:
+
+
Fixes a bug in machines when switching between speedy and normal processing speeds.
+
+
Dave-TH updated:
+
+
Adds the access tuner, a syndicate device for interfacing with airlocks. Try it out!
+
+
Farie82 updated:
+
+
Clings now appear dead on medical huds when using regenerative stasis
+
+
R1f73r updated:
+
+
Admin Character names will no longer appear in adminhelps
+
+
TDSSS updated:
+
+
Allow , in names, Kidan of the world, rejoice
+
Made kidan random name generation less shitty
+
+
Triiodine updated:
+
+
ghost role sprites with a palette more depressed than the playerbase
+
medical doc spawn to ghost station
+
Xydonus's second fluff item
+
+
+
03 November 2018
+
Certhic updated:
+
+
Added diona nymph action buttons
+
Added diona nymph resist alert when they're merged
+
Diona nymph can now initiate merge with the gestalt
+
Diona nymph can now leave their gestalt by resisting
+
Diona nymph can no longer attack its gestalt
+
+
Farie82 updated:
+
+
Security comments now work again. Sec hud arrests will now function as intended.
+
+
Fox McCloud updated:
+
+
Fixes exploit involving materials and the recycler
+
+
Jazz23 updated:
+
+
A method of uploading coordinates to perma teleporter circuit board.
+
+
variableundefined updated:
+
+
Tigercat2000 & variableundefined (Ansari) to the maintainer list.
+
+
+
02 November 2018
+
Purpose updated:
+
+
After over 100 years in cryosleep, a few cryocells are starting to open... AncientStation ghost roles are now available.
+
Adds a ghost role menu, available under the Ghost menu
+
Adds an all-access Air Alarm for mappers to utilise.
+
Adds glowsticks. Currently only available in AncientStation.
+
+
variableundefined updated:
+
+
Attack log to stun gloves
+
+
+
01 November 2018
+
Citinited updated:
+
+
A disposal nullspace bug.
+
+
Farie82 updated:
+
+
Repairing a mech now says you're doing it to the others balance: Mechs now take time to repair. No more spam repairing
+
Random news feed now does not contain random code.
+
+
Mitchs98 updated:
+
+
Lowers the spam you receive from entering a warm or cold pool. You will no longer receive 'The water is quite warm.' nearly every few seconds.
+
Headslugs no longer teleport out of closed lockers upon bursting.
+
+
Warior4356 updated:
+
+
Ghosts can no longer re-enter a drone that has been shut down.
+
+
+
31 October 2018
+
Arkatos updated:
+
+
Fixes Rewriter drink description typo.
+
+
Jountax updated:
+
+
Renamed Ice Peppers to Chilly Peppers.
+
+
TatsumakiMagi updated:
+
+
fixed merch shop, arcade shop and the give command working from a distance
+
+
+
30 October 2018
+
Dave-TH updated:
+
+
Adding a paper to a paper bundle no longer automatically opens the bundle.
+
+
Farie82 updated:
+
+
Items dropped in a space pod are now under the seat. No more magical dropping out of the pod
+
Cargo can now buy oil tanks.
+
+
Warior4356 updated:
+
+
Megaphone now handle speech impediments properly
+
Swiping an ID through a drone no longer causes a runtime and correctly shuts it down
+
Silicons are now able to open a door linked to a button regardless of proximity
+
+
uc_guy updated:
+
+
You can no longer table people through walls/doors/shutters.
+
+
warior4356 updated:
+
+
fixed the holosign in surgery1
+
+
+
29 October 2018
+
Farie82 updated:
+
+
Round start time is now variable. Defaults to 240 if not filled in
+
+
Mitchs98 updated:
+
+
Re-Adds a Guest Pass terminal to Medbay front desk.
+
+
Squirgenheimer updated:
+
+
regular mining satchels will now only hold 10 slots of ore stacks instead of 50
+
Deleting mechs no longer causes a runtime
+
Mech speech bubbles should now follow the mech.
+
+
gatchapod updated:
+
+
Fixed airlocks electrocuting people remotely through open UI
+
+
+
28 October 2018
+
Dovydas12345 updated:
+
+
Fixed being able to pull when incapacitated
+
Fixes catching two handed items with one hand.
+
+
Fox McCloud updated:
+
+
changes the oil can sprite
+
Colorful Reagent changes your blood color
+
+
Mitchs98 updated:
+
+
Adds the Security Jacket to the standard sec gear lockers, an alternative to the standard armor vest that covers more area but protects less. Style matters.
+
+
Normalyman updated:
+
+
Fixed being able to open containers via dragging, while being incapacitated.
+
+
Ty-Omaha updated:
+
+
Pulling fixed
+
Better way of fixing hostile mobs not attacking
+
Hostile mobs attack again instead of nuzzle
+
+
uc_guy updated:
+
+
Fixes shadowling game mode delaying the game ticker
+
+
+
27 October 2018
+
AffectedArc07 updated:
+
+
Removed catgirls, be gone foul beasts
+
+
Alonefromhell updated:
+
+
Runtime in species.dm, 620 fixed
+
Stable LDM and Sorium creates their vortexes properly now.
+
Inject chems into all your favorite types of smokeables, TODAY!
+
Backend: Added dummy vortex reagents to prevent further runtimes.
+
+
Certhic updated:
+
+
fixed wrenched down unconnected pipes being invisible
+
fixes invisible diona observers
+
Fixes simple animals attacking while they were on help intent.
+
+
Farie82 updated:
+
+
Dusting a mob now dusts everything he holds and has equiped
+
fixes animals activating the paperfolding proc. No more runtimes there
+
One less piano runtime
+
fixes the runtime in the AI code. You now get messages if you lose power and stuf.
+
Fixes the runtime in Landmarks
+
+
TDSSS updated:
+
+
HoP's door remote has access to his office doors + supply doors now
+
+
tigercat2000 updated:
+
+
Pretty radial menu for the RCD!
+
SSoverlays human mobs
+
Catgirls!
+
/tg/'s catgirl refugees
+
Ears are now organs
+
The suffering of thousands of displaced kittens
+
+
uc_guy updated:
+
+
Fixed roller beds not going to their "down" position.
+
You can now tell if a borg has suicided by examining them
+
+
+
26 October 2018
+
Mitchs98 updated:
+
+
Unary vents, scrubbers, passive vents, connectors, air injectors, and pipe caps now orientate as intended when using Orientate Automatically with an RPD.
+
Fixes #8036, Door controls not respecting range for pod doors.
+
Now when holding a flag it won't be stabbing into your characters face. Burning a flag also won't magically change its orientation.
+
+
dovydas12345 updated:
+
+
Fixes ghosts being able to unflip flipped tables.
+
+
uc_guy updated:
+
+
Syndicate communication channel is now pseudonymous.
+
+
+
25 October 2018
+
Aurorablade updated:
+
+
welders will now fix external IPC leaking. My Bad.
+
+
Birdtalon updated:
+
+
User responses not being appended to admin tickets
+
+
Dave-TH updated:
+
+
Adds surgical trays! You can drag these cool tables around and the items placed on them come along for the ride! Nifty!
+
+
Farie82 updated:
+
+
Objectives now get fully removed when removing them admin style. Removing the assassinate cryo message if you were de antagged.
+
+
tigercat2000 updated:
+
+
PiP Hud Elements
+
AI PiP Multicam - Enabled by admins
+
Calling /New( with excess arguments is now properly directed to /Initialize(
+
+
+
24 October 2018
+
Alonefromhell updated:
+
+
Mind check in pre_quip added, to prevent runtime.
+
+
Birdtalon updated:
+
+
Backend cleanup of assembly.dm and proximity.dm
+
+
Certhic updated:
+
+
Runtime error in CureIfHasDisability
+
Borg health is now updated after being repaired
+
+
Farie82 updated:
+
+
Tablets now spawn correctly. No more buying (seemingly) broken tablets
+
+
Fethas updated:
+
+
Ipcs bleed oil. Bleeding can be patched by welders and organ mainp surgery(if you have to heal an ipc via surgery we may as well take that out too).
+
Kidan biolum slightly brighter. tweak:Vox now become confused and unintellible(..more) on cort stack damage.
+
+
Warior4356 updated:
+
+
Safe tumbler 2 no longer makes I am open noise when turning tumbler 1.
+
+
dovydas12345 updated:
+
+
Added data disk to misc designs.
+
+
variableundefined updated:
+
+
Using reagent dispenser like fuel and water tank no longer give you an attack cooldown / animation.
+
Tracking for shadowling win rate. Improved parsability for other win/loss round type's win rate.
+
+
+
23 October 2018
+
Alonefromhell updated:
+
+
You should now be able to put all your favorite chems in food again.
+
+
Fox McCloud updated:
+
+
Reagents now GC slightly better
+
+
+
22 October 2018
+
Dave-TH updated:
+
+
Fancy tables now properly smooth.
+
+
MrStonedOne updated:
+
+
Fixes a cause of lag in the Timer subsystem
+
+
Purpose updated:
+
+
Removes unused code in Nuclear gamemode.
+
Removes some empty icon files.
+
Fixes a typo in an SDQL parse warning.
+
Code improvement with timers in Revolution gamemode.
+
+
name here updated:
+
+
The autopsy scanner now works even when it does not know the weapon and/or the time of death.
+
Unused weapon chance code
+
+
uc_guy updated:
+
+
Removed logging ambiguity for uplink purchases.
+
+
variableundefined updated:
+
+
Component refactor from tg made by ninjanomnom has been ported over. Report unexpected issue (with autolathe / ORM)
+
+
+
21 October 2018
+
Alonefromhell updated:
+
+
Fixed some formatting issues in post_equip.
+
+
Ansari updated:
+
+
Oculine processing should be less expensive now.
+
+
Desolate updated:
+
+
Refactors some reagent lists into global list
+
+
Farie82 updated:
+
+
Cyborgs can now refill welding tools and fire extinguishers using the recharging station
+
Oculine now updates the blindness status correctly
+
Added the Viral Injector. A virologist specific traitor item that acts like a sleepy pen but can transfer viruses. It's disguised as a functional pipette.
+
+
Purpose updated:
+
+
Moves Icon Smoothing to a Subsystem.
+
Atom code will no longer track a list atoms, for literally zero reason.
+
Fixes grammatical error in the suit storage unit
+
+
Shazbot194 updated:
+
+
all north facing in hand icons for flags.
+
+
Squirgenheimer updated:
+
+
Explosive holoparasite booby traps will now behave better, such as correctly triggering on mobs
+
+
Triiodine updated:
+
+
Skrell & Tajaran sechardsuit to paracode palette, from Bay12 palette.
+
TG & BS12 sec-hardsuits in all dmis
+
+
Warior4356 updated:
+
+
Final UI update was missed in Safe Refactor PR
+
+
name here updated:
+
+
Holodeck plating sprite is now back to the old one.
+
+
tigercat2000 updated:
+
+
We're going 512 boisssssssssssssss
+
+
variableundefined updated:
+
+
Improves the List free slots admin verb to show useful information.
+
Cyborg hypospray's attack log message should no longer be reversed.
+
How containers work is now standardized in the back-end. There might be unexpected or odd bugs with containers and reagent transfer, please report them.
+
Minor refactor of revenant code.
+
Some relative path & commented out code has been cleared up in code. Report unexpected issues.
+
+
+
20 October 2018
+
Birdtalon updated:
+
+
Spacepods explosions are significantly reduced.
+
+
Dapocalypse updated:
+
+
Adds password protected files to modular computer.
+
+
Farie82 updated:
+
+
Guardian injectors now tell in their examination text if they are spend or not.
+
Added feedback on the RCD airlock access topic.
+
+
Fox McCloud updated:
+
+
Updates the Garbage SS so it's less likely to induce lag
+
+
Purpose updated:
+
+
Suit storage units now contain magboots for relevant roles.
+
Adds the captains jetpack to his suit storage unit, so it is now stealable again on Delta.
+
Aluminum & Aluminium properly standardized.
+
+
craftxbox updated:
+
+
added check to make sure person downloading pAI isnt dead.
+
+
uc_guy updated:
+
+
It is no longer possible to duplicate uvents.
+
+
variableundefined updated:
+
+
Plating's icon is back to the old one once again.
+
+
+
19 October 2018
+
Fox McCloud updated:
+
+
Fixes round-start sparks being stuck in maintenance
+
+
Purpose updated:
+
+
Fixed an issue with Space Vine mutations
+
+
SpaceManiac updated:
+
+
The body zone selector now indicates which body part you are about to select when hovered over.
+
+
TDSSS updated:
+
+
New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter ripleys.
+
+
Triiodine updated:
+
+
new DNA Sampler Sprite
+
+
Warior4356 updated:
+
+
Added nanoui for safe. Added minor quality of life to safe.
+
Removed old UI from safe
+
Safe now is only Right - Left - Right. Safe is 0-99 rather than 0-71.
+
Added safe dial for it's nanoui.
+
+
+
18 October 2018
+
IrkallaEpsilon updated:
+
+
Feral Cat grenades are now listed as job specific items.
+
+
Shazbot updated:
+
+
Shazbot's custom cyborg sprites.
+
+
Squirgenheimer updated:
+
+
Ghosting from cryopods with an inventory open should no longer cause a runtime
+
+
Triiodine updated:
+
+
disposals pipes sprite offsets & stray pixels.
+
id_decal icons
+
arcade id_decals using mind batterer sprite. (That's just silly.)
+
+
+
17 October 2018
+
Alonefromhell updated:
+
+
Added a Nanotrasen Navy Uniform to the blueshields locker
+
+
Crazylemon updated:
+
+
Buildmode is now compatible with 511 clients.
+
+
FalseIncarnate updated:
+
+
Floodlights will now shut off if lacking a power cell.
+
+
Fox McCloud updated:
+
+
Fixes the Timer SS timing out when it shouldn't
+
Fixes reagent overdose runtimes
+
+
TDSSS updated:
+
+
Examining a borg tells you what module it has loaded
+
+
datlo updated:
+
+
Added the Honk Brand Infiltration Kit to Nuke Ops.
+
+
+
16 October 2018
+
FalseIncarnate updated:
+
+
Corpse spawners (such as those on the Wild West away mission) now properly spawn corpses at roundstart that don't remain standing.
+
+
+
15 October 2018
+
FreeStylaLT updated:
+
+
Crunchy sounds when bones are broken
+
+
Squirgenheimer updated:
+
+
Changelings will now wake up after using Regenerative Stasis.
+
+
TDSSS updated:
+
+
The maximal length of a name that won't be rejected as a 'bad name' has been raised.
+
+
Ty-Omaha updated:
+
+
Fixes stunbaton runtime (Stun() being called on a turf)
+
Borers with their "Dominate" window already open can no longer run across the map and successfully cast the spell on those people, they must be within 7 tiles (default view range)
+
Borers can no longer spam open the "Dominate" spell
+
Borers with their "Dominate" target window already open can no longer successfully target someone if they are dead
+
Borers no longer "slither up and probe people's ear canal" if they select the target of an "infect host" spell after they die
+
+
uc_guy updated:
+
+
You can no longer roll around when dead.
+
+
+
14 October 2018
+
Purpose updated:
+
+
Makes it so that Screwdrivers & Wirecutters are no longer invisible in the map editor.
+
Fixes a gibbing runtime
+
+
taac updated:
+
+
added cryo cell description
+
+
uc_guy updated:
+
+
fixed runtime in IsBanned.dm
+
+
variableundefined updated:
+
+
Stacks are split by CtrlShiftClick instead of AltClick now.
+
A runtime that occurs with paper bundle being created with one or less paper.
+
+
+
13 October 2018
+
Birdtalon updated:
+
+
Chem master now will show its de-powered state properly.
+
+
DarkPyrolord updated:
+
+
Changed attack log level for reagent forcefeeding from FEW to MOST
+
+
FlimFlamm updated:
+
+
Tweaked formatting of Newscaster stories
+
Fixes images displaying improperly on Newscaster stories
+
+
Ty-Omaha updated:
+
+
Boxing logs moved to the ALL preference
+
+
alex-gh updated:
+
+
Species damage modifiers now only affect damage, not healing.
+
Races that took more damage from certain damage types no longer heal from that damage type faster. For example: Drask no longer heal from burn at double rate; Grey, Vox no longer heal from brute at increased rate (Note: IPC healing with welders/wires is not affected).
+
Kidan no longer heal from brute at a reduced rate.
+
+
uc_guy updated:
+
+
You can no longer get an infection and die during abductor surgery.
+
Voice analyzers no longer activate on noise.
+
+
+
12 October 2018
+
Alonefromhell updated:
+
+
META - Cargo shuttle blast doors now reacts to the right button.
+
META - Cargo shuttle airlocks now bolt properly.
+
META - Cargo shuttle flaps are now airtight. All hail Cargonia.
+
+
Birdtalon updated:
+
+
Gamma ERT Paranormal gets their null rod.
+
Moves check_and_add() to reagents holder
+
+
DesolateG updated:
+
+
Refactors global var lists to use the global subsystem.
+
+
Farie82 updated:
+
+
Added the on_give proc for items. Was needed for the fixes
+
Giving two handed items like the DIY chainsaw and potted plants now works correctly
+
The DIY chainsaw, doomslayer chainsaw and the potted plants now do damage when given to somebody else and when picked up while the chainsaw was on.
+
+
Purpose updated:
+
+
Cyberiad's grimy tiles are now actually dirty and cleanable.
+
Delta's grimy tiles are now actually dirty and cleanable.
+
Ironsand is now visible in the Map Maker.
+
Away missions updated with the appropriate dirt/grime so that it is now cleanable.
+
Fixes stool's unique suicide message.
+
Fixes rollerbeds no longer going through plastic flaps.
+
+
TDSSS updated:
+
+
Removed Skrell discrimination, allows ! character in IDs (agent IDs or made via ID computer)
+
+
variableundefined updated:
+
+
Ore now represented by stack that holds up to 50 items. Should reduce lag with ORM greatly.
+
Satchel can only carry ten items instead of 50 items. You should end up carrying more ore in total however
+
Fire acting on ore means they would be refined with 50% efficiency.
+
Stack merges automatically if dropped on the floor, or a new stack is created. This doesn't happens on your body.
+
They also merge if you drag them over eachother.
+
Alt-click split a stack
+
You can throw sand into people's eyes! Pocket sand!
+
Phazon take 5 bluespace crystal to construct now instead of 1. remove: Transfer prompt when you click on a stack of the same type with a stack
+
+
+
11 October 2018
+
Citinited updated:
+
+
Fixes an oversight in autopsy report drawer's description.
+
+
Farie82 updated:
+
+
NPC's now initialise correctly. Removing a lot of runtime errors.
+
+
Kyep updated:
+
+
Fixed the admin ERT panel not working correctly if the admin using it was playing as a carbon mob.
+
+
Stork Industries updated:
+
+
Fixes "Arachno-Man's" boots
+
+
Triiodine updated:
+
+
SLOT_MASK from necklaces.
+
thatdanguy23's fluff item
+
+
+
10 October 2018
+
Alonefromhell updated:
+
+
You should no longer be able to relight a burned match by using a shoe.
+
+
Birdtalon updated:
+
+
Small runtime in tickets.dm
+
Mulebot teleportation exploit.
+
Iron sand icons now render correctly.
+
+
Citinited updated:
+
+
Emagging a locker will keep the original description instead of telling you it was emagged twice.
+
Examining airlocks displays the proper icon now
+
Holopads don't work when unanchored any more.
+
+
Purpose updated:
+
+
Fixes a few broken tiles in maintenance, by breaking those tiles properly.
+
+
Purpose & AndrewMontagne updated:
+
+
New grimy dirt sprites.
+
Dirty tiles now get dirtier if neighbouring tiles are also dirty.
+
+
Triiodine updated:
+
+
new sprites for cup-chicken soup, icecups, weight loss shakes.
+
cup to can of chicken soup.
+
+
Ty-Omaha updated:
+
+
Fixes PAIs
+
Ambulances work again
+
+
Warior4356 updated:
+
+
added Grey sprite for psysuit, made by dumbdumb
+
+
tigercat2000 updated:
+
+
Hovering over an inventory slot now shows an indicator for if that item can go in that slot or not. Pretty!
+
SSOverlays has been added, but not implemented!
+
+
+
09 October 2018
+
Alonefromhell updated:
+
+
Edited the attack text of the teleport armor.
+
+
Birdtalon , LPSpartan, Shazbot, Memager updated:
+
+
Portable Body Analyzer for ERT
+
Muilti Lens Immolation gun for gamma ERT
+
PDW-9 sidearm for ERT
+
T4 Thermite Charge for Gamma ERT security
+
Sprites for gamma ERT suits
+
Red ERT loadouts
+
Gamma ERT loadouts
+
+
Citinited updated:
+
+
Conveyor belts have received a facelift!
+
Rotating a belt with a wrench now nicely rotates the belt for you
+
Click a lever with a lever to link their IDs. Click a belt with a lever to link that belt to that lever.
+
Deconstructing a syndicate console will no longer ruin it forever.
+
+
DesolateG updated:
+
+
Refactors the timer subsystems and bugfixes
+
+
Purpose updated:
+
+
Code improvements on mouse_opacity
+
Plating shadow faux 3d now works properly.
+
+
Purpose & AndrewMontagne updated:
+
+
Adds tile smoothing to plating. Plating should now be a bit more of a 3d look...
+
+
Purpose & Birdtalon updated:
+
+
Takes Runtime out of the oven.
+
+
Squirgenheimer updated:
+
+
fixed a potential runtime in the sentient animal event
+
+
Triiodine updated:
+
+
Tidied up nuclear shuttle's mini-medbay to better utilize the space provided.
+
Full Body-Scanner, surgery set, replacement limbs, bloodpacks to the nuclear shuttle's mini-medbay.
+
One of the nuclear shuttle's sleepers.
+
+
uc_guy updated:
+
+
Legless human mobs no longer scream non-stop when buckled into a chair.
+
+
variableundefined updated:
+
+
Poolcontroller performance are improved dramatically. Expect slightly reduced CPU use on beach gateway map
+
Poolcontroller will no longer work properly if you directly var-edit someone's location to inside a body of water and a decal's (However if the mob move right after it will still work)
+
+
+
08 October 2018
+
Ansari, Birdtalon updated:
+
+
Updates resting procs, fixes getting people up from help intent.
+
+
Birdtalon updated:
+
+
Conservation of damage mechanic for set species
+
Changeling transform conserves damage when transforming to a different species.
+
+
Crazylemon updated:
+
+
Fixes AIs being unable to examine due to a runtime.
+
Fixes nearsighted glasses behavior being inverted (seeing worse with glasses).
+
Mining mobs now update their sprites on death.
+
+
Crazylemon64 updated:
+
+
Updates for damage on HUD elements are now instant for cyborgs and humans.
+
When dead, you can now see your surroundings with ghost vision and examine things around you.
+
+
Farie82 updated:
+
+
PANDEMIC can print a virus release form now. Viromancers REJOICE!
+
+
Purpose updated:
+
+
Adds the missing turfs under windows & doors on Mech Transport Space ruin.
+
Fixes improper turf in the shuttle crashed into one of the space ruins.
+
Fixing improper decals & missing turfs in the Space Bar space ruin, and some tiny fixes.
+
GasTheLizard Space Ruin now uses Decals properly.
+
MoonOutpost19 Away Mission now uses Decals properly.
+
Evil Santa Away Mission now uses Decals properly.
+
Fixes the corpse spawners in Space Battle Away Mission.
+
Space Battle Away Mission now uses Decals properly.
+
Prettier Donate/Karma buttons!
+
Adds new stair sprites.
+
Blackmarket Backpackers now uses Decals properly.
+
OneHalf Space Ruin now uses Decals properly.
+
CentComm Away Mission now uses Decals properly.
+
Cyberiad Z2 now uses Decals properly.
+
Space Hotel Away Mission now uses Decals properly.
+
Terror Spiders Away Mission now uses Decals properly.
+
Adds plasma window spawners for mappers.
+
Thrown stunbatons & improvised batons have a low chance to stun.
+
You can now alt click breath masks to pull them up & down.
+
You can no longer erroneously pull down a vox mask.
+
TravisCI now checks all space ruins & away missions for integration.
+
+
Triiodine updated:
+
+
Rsik's fluff katana ~~modkit~~
+
+
Ty-Omaha updated:
+
+
Replaces Security's bomb suit with their cooler Security version
+
Fixes runtime in world.dm;127
+
+
tigercat2000 updated:
+
+
Made mind.dm 1/1000 less awful.
+
+
variableundefined updated:
+
+
NPCpool (SNPC) is now a subsystem.
+
NPCAI (For simple mob) is now a subsystem.
+
Customising SNPC no longer results in screaming death and a naked person.
+
Logging added to RD teleport gun, some projectile are always logged
+
EMPulse & Explosion can optionally log a cause for administrative purpose
+
Backend Attack logs now display coordinates of attacker & defender for forensic reconstruction.
+
Grill shock cooldown is 1 second instead.
+
+
+
07 October 2018
+
Birdtalon updated:
+
+
Ammo boxes now return materials proportional to their contents when recycling, nullifying infinite ammo exploit.
+
+
Farie82 updated:
+
+
Fixing a disability now fixes the gene related to it if needed. No more free gene stability from blindness and such
+
fixed bluespace disposal bins
+
instant recall doesn't fuck up disposals
+
meteor shots now deconstruct the disposals unit, removing weird behaviour
+
+
Purpose updated:
+
+
Winged chairs now get placed back down correctly as winged chairs.
+
CyberiadAI Discord Bot now announces which station is being used.
+
Less things will refer to the NSS Cyberiad when not actually ON the NSS Cyberiad.
+
Decals now Initialize()
+
+
SkeletalElite updated:
+
+
Fixed grammar in meat spike's name
+
Chaos Holoparasite's abilities actually work
+
+
datlo updated:
+
+
Changelings with wingdings now permanently switch to regular speech after transforming
+
+
variableundefined updated:
+
+
All sharp items can cut sliceables like cheesewheel now.
+
Putting items inside sliceables is done by alt-click now.
+
+
+
06 October 2018
+
Alonefromhell updated:
+
+
META - Cryogenics now has a Cellcharger.
+
+
Purpose updated:
+
+
Delta - Adds a Paramedic's Office.
+
Latejoining autotraitors should now have their uplinks again.
+
You can now pick up most chairs and beat colleagues with them. Careful too many whacks and they'll break.
+
Adds new bar stools.
+
Delta - Removes extra door in arrivals.
+
+
Squirgenheimer updated:
+
+
Victims of changeling swap forms and wizard mindswap can now re-enter their corpses
+
+
+
04 October 2018
+
Alonefromhell updated:
+
+
Sensory Restoration should now work with Ocular Restoration.
+
+
Farie82 updated:
+
+
borgs can now heal their patients while there is a surgery going on.
+
+
Purpose updated:
+
+
Boxstation: Fixed a number of turf/decal/overlay issues
+
Boxstation: The poster in medbay maintenance now displays properly...
+
Boxstation: Xenobio slime cameras should no longer be able to see into maintenance.
+
Boxstation: Adds missing firelock to vacant office.
+
Boxstation: Moves Medbay AIR Alarms around to more functional locations.
+
Boxstation: Fixes 'fake grass' in the kitchen area.
+
Boxstation: Fixed several issues were Radiation Storm events could bleed into maintanence.
+
Boxstation: ALL catwalks should now be able to see space through the holes.
+
Delta - Adds fuel depo to the hanger.
+
Delta - Adds the Nullrod & Shard to the Chaplain's back office.
+
Delta - Fixes the invisible wardrobe in the dorms.
+
Delta - Adds a few art vendors across the station.
+
Delta - Adds the buttons to the Perma Airlock.
+
Delta - Doctors now have access to the patients rooms. Oops.
+
Delta - Adds the Coroner's spawn point in the morgue.
+
Delta - Increases blood packs in medbay, by random blood spawners.
+
Delta - Fixes the exit button of Medbay.
+
Delta - Increases the size of the atmos space loop.
+
Delta - No longer can maintenance fire lasers at the Supermatter....
+
Delta - Added some wiring to make it easier to emitter the SM.
+
Delta - Extends the wiring out of solars airlocks in atmos solars.
+
Delta - Atmos now have access to Atmos solars.
+
Delta - Adds an additional atmos void suit.
+
Delta - Adds two additional engineering void suits, but into secure storage.
+
Delta - Fixes the missing airlock cycling on an atmos airlock.
+
Delta - Adds the missing multi-tool to atmospherics.
+
Delta - Fixed Mixed Air & Gas Mix computers access to the tanks & sensors.
+
Delta - Can now cross parts of the transit tube.
+
Delta - Garbage disposal is now functional.
+
Delta - Disposals no longer fires trash into the atmos office.
+
Delta - Atmos techs now have access to the jetpacks in EVA.
+
Damaged plating when fixed, now loses the aesthetic damage too.
+
Yellow closets now use the correct icons.
+
+
+
03 October 2018
+
Farie82 updated:
+
+
Your hands won't become the surgeons hands anymore in surgery
+
+
Fethas updated:
+
+
Cryostorage ghost role spawners for ruin/mapping/adminbus. Also refactors corpse landmark code.
+
+
FreeStylaLT updated:
+
+
Remapped Medbay Lobby.
+
Moved the cell charger from Cryo to the break room.
+
Added a cell to Medbay's break room.
+
+
+
02 October 2018
+
Birdtalon updated:
+
+
Small formatting fix in soulstone.dm
+
+
Kurgis updated:
+
+
The chief engineer jumpsuit no longer appears as a green suit when held in-hand.
+
Added a new in-hand sprite for the chief engineer jumpsuit from Polaris.
+
+
Purpose updated:
+
+
Delta Station, codenamed Kerberos has been acquired by Nanotrasen.
+
Wizard Academy now uses decals
+
Wizard Academy misplaced wires fixed
+
+
Tails2091 updated:
+
+
Claw Game is now a bit easier to use. Slower speeds, still receive prize when interrupted, and auto-close.
+
Claw Game has correct window size, centered buttons, general code cleanup.
+
+
name here updated:
+
+
Remove canvas and easel from Deltastation
+
+
tigercat2000 updated:
+
+
Chat no longer horribly breaks at the first high-ascii character.
+
+
+
01 October 2018
+
Aurorablade updated:
+
+
adjusts to Arachno-Man suit fluff.
+
+
Birdtalon updated:
+
+
Admin ticket subsystem - migrates existing global datum.
+
+
Dapocalypse updated:
+
+
Added a grille cooldown to prevent alt-click spam someone on a grille to instantly husk people.
+
+
Farie82 updated:
+
+
Not being able to place chutes over tiles with multiple pipes.
+
+
Purpose updated:
+
+
CPU Performance in get_area proc
+
Excavates a few relics from area code.
+
Metastation - Escape Shuttle windows are now breakable again.
+
Metastation - Medbay camera no longer floating in mid-air.
+
Metastation - Adds the missing component analyzer to Robotics.
+
Metastation - Fixes the wiring issues in Medbay.
+
Metastation - Fixes the wiring issues in Virology.
+
Metastation - Fixes the lack of fungus on the map, placing it near water sources in maintenance.
+
Metastation - Fixes area definition, so that admins can now send people to cryo.
+
Metastation - Fixes bizarre map corruption from the Arcade PR which turned Coroners into a bit of an arcade....
+
Metastation - Law office's shutters now grant privacy properly.
+
Metastation - Fixes the lack of inflatables & pipe painter in Atmospherics
+
Metastation - Adds a second atmos locker, as one is lower than number of atmos slots available....
+
Metastation - Properly marks airless tiles by the hanger as airless.
+
Metastation - Hooks up Security's Camera Computer to the station's cameras...
+
Metastation - Fixes the floating fire alarm in Security.
+
Metastation - Fixes the detective's lack of Evidence Storage access...
+
Metastation - Captain, IAA and NT Rep's fax machines are hooked up properly. Bloody IT department...
+
Metastation - Security cannister attachment is now attached to the pipe grid.
+
Metastation - Bots now correctly patrol the station again.
+
Metastation - Updates the turfs & decals to use the correct decals.
+
+
Purpose & AndrewMontagne updated:
+
+
Tiles now retain the styling when damaged.
+
Tile damage now uses decals, and can be mapped easier.
+
+
TDSSS updated:
+
+
RnD server control console's data management now works, allowing for deletion of research levels and known techs.
+
fixed minor typos.
+
bluespace polycrystals can now correctly be broken down while floating in space.
+
+
variableundefined updated:
+
+
Nano Mob Hunter ported to StonedMC. Report unexpected issues.
+
Shuttle has been ported over to the StonedMC Subsystem.
+
+
+
30 September 2018
+
Crazylemon updated:
+
+
Corrects a comment in the code regarding IPC damage.
+
+
Purpose updated:
+
+
Fixes various message format overflows.
+
+
Shazbot updated:
+
+
You can now remove KA mods from borgs.
+
+
TDSSS updated:
+
+
Plasma statues and walls are no longer ignited by laser tag guns or practice lasers.
+
Crowbars can no longer make pool water invisible.
+
+
datlo updated:
+
+
Made the poison pen available to traitor librarians
+
+
variableundefined updated:
+
+
One click antagonist giving antag to people in restricted job.
+
+
+
29 September 2018
+
Dapocalypse updated:
+
+
Removes extra penlight given to plasmemes.
+
+
DarkPyrolord updated:
+
+
Pyro's fluff item
+
+
Kyep updated:
+
+
Fixed several bugs with blob, including lateround blobs not generating biohazard alerts, blobs missing out on early resources they should have, and a bug with blob storage being broken that prevented blobs getting any resources.
+
+
NoWolfie updated:
+
+
New Pyr'kus cult floor and wall sprite.
+
+
Triiodine updated:
+
+
Nukies spawning with cybernetic organs/limbs
+
+
Ty-Omaha updated:
+
+
Removes canvases due to everybody crashing from them.
+
+
farie82 updated:
+
+
Headbutting the airlock is more consistent.
+
refactored the airlock code.
+
Using multitools and such on a door with a note now doesn't remove the note. Only grabbing with an empty hand now.
+
+
+
28 September 2018
+
DarkPyrolord updated:
+
+
Fixes a ten year old atmos bug, fix will cause toxins bombs and plasma fires to be a little less lethal
+
Readds modkit sprites to items.dm to fix invis fluff item modkits.
+
+
Farie82 updated:
+
+
No more broken tile due to getting shot out of disposals.
+
Point blank shots not hitting the correct person. When multiple people are on the same tile.
+
+
Kyep updated:
+
+
The wild west away mission no longer offers hijack traitor status as a potential reward.
+
Deconstructing/reconstructing the space pod fab no longer turns it into a mech fab. No more mechanics building surprise mechs.
+
The spacepod fab circuit is now buildable in R&D.
+
Spacepod fabs now require mechanic access to use, like the mechanic R&D console does.
+
+
Purpose updated:
+
+
Mappers can now have Floodlights round-start enabled.
+
+
Tails2091 updated:
+
+
Refactored Hallucinations to match contribution guide standards a bit more.
+
+
Triiodine updated:
+
+
Fixes jade lipstick being lime.
+
Adds lime lipstick.
+
New storage implant icon
+
+
Ty-Omaha updated:
+
+
Ambulances now have sirens!
+
Shadowlings no longer are able to target simple animals (mice)
+
+
farie82 updated:
+
+
fixed cling transformed humanoids looking rather pale.
+
Fixed emagged camera consoles not opening the tabs
+
+
uc_guy updated:
+
+
Vox auto equip the nitrogen tank when spawning if possible.
+
Nitrogen tanks no longer overwrite job items.
+
+
variableundefined updated:
+
+
Benjaminfallout's fluff item.
+
Qdel log is now re-added to the garbage subsystem to enable coders to investigate sources of hard delete.
+
When you remove a light tube while lying down, the light tube disappear. This no longer happens.
+
Latejoin AI no longer spawn in naked at arrival shuttles.
+
Not spawning in with your memory of bank account at roundstart...
+
+
+
27 September 2018
+
Anasari updated:
+
+
You can now deconstruct a fire extinguisher cabinet to yield a single piece of metal. You can construct them for five pieces of metal, with extinguisher included. (Using metal construction menu)
+
+
Birdtalon updated:
+
+
Borg modules now add item action buttons if present.
+
Beepsky responds to attacking him with disarm intent.
+
+
CornMyCob updated:
+
+
Adds in a prompt for becoming a headslug.
+
+
Crazylemon64 updated:
+
+
Adds a fluff item for ELO
+
+
DesolateG updated:
+
+
Added a check to whispering adverbs to prevent double adverbs while whispering.
+
+
FalseIncarnate updated:
+
+
Adds mixing bowls, which allow you to cook multiple recipes at the same time! The dinnerware vendor comes pre-stocked with 10!
+
Adds 2 mixing bowls to the Food Crate from cargo should you need additional. This is the same crate that includes the extra bottle of enzymes.
+
Burned messes now scale their carbon and "????" content with both physical ingredients and directly inserted reagents while burning in the cooking machines.
+
Upgraded cooking machines now attempt to evenly distribute reagents from ingredients across all produced results, rather than just the original.
+
+
Farie82 updated:
+
+
You can remove notes from an airlock now with the grab intent using an empty hand.
+
+
Fox McCloud updated:
+
+
Fixes 128x128 menu location
+
+
Kyep updated:
+
+
Refactored shieldgen.dm, fixed a bug which could cause shieldgens to behave improperly under some rare conditions.
+
+
Purpose updated:
+
+
CPU Performance tweaks in the Bananaium floor honks & squeaks
+
Capitalisation correction in automated chef npcs
+
CPU Performance tweaks in the Xeno Hunter tackles
+
CPU Performance tweaks in Malf AI
+
NT Formal clothing now updates to the station names correctly.
+
Fixes typos in NT Formal clothing
+
Minimap is now updated
+
Holopads now use the correct amount of power.
+
CPU Performance tweaks in the Pipe Dispenser
+
Blobs now delete light fixtures correctly.
+
use_power variable is more clearly defined as non-boolean via defines.
+
+
TDSSS updated:
+
+
Atmospherics external airlocks can now be controlled by borgs and AIs
+
+
Triiodine updated:
+
+
righthand fork sprite being oriented wrong.
+
+
Ty-Omaha updated:
+
+
Fixes vending machine bank account security. You can now use them with a bank account security level above zero.
+
Fixes a bunch of \ tags
+
+
alex-gh updated:
+
+
Drask no longer take damage from cryokinesis
+
Cryokinesis deals less damage, but lowers the body temperature a lot more.
+
Autopsy scanner now prints all times in human readable format.
+
+
datlo updated:
+
+
Added the wizard spell Greater Knock, letting them remove all access restrictions on the Cyberiad and master door opening.
+
+
variableundefined updated:
+
+
drop_location & AllowDrop() has been ported over from tg. Report unexpected issues with dropping items.
+
When you late join, extra items you can't equip / hold spawn on the ground instead of in the lobby screen. Including vox medkit etc.
+
Plasmaman no longer get double the firepower when spawning in as Captain, BS, or sec roles.
+
Non-human's DNA (Except for IPC, of course) should show up properly in the DNA modifier now.
+
+
+
25 September 2018
+
Birdtalon updated:
+
+
Secure console UI (security records) appears bigger by default.
+
One-click-antag now respects game-mode's protected jobs.
+
+
Fox McCloud updated:
+
+
adds support for 128x128 skin interface pixel size for 4K monitors
+
+
Purpose updated:
+
+
Space is now visible under corner pieces of the Intact Empty Ship ruin.
+
+
+
24 September 2018
+
Triiodine, Desolate, updated:
+
+
Things without blood bleeding red when rolled over by a mulebot.
+
+
+
19 September 2018
+
Birdtalon updated:
+
+
Screwdrivers now open fire alarms instead of wirecutters.
+
+
+
18 September 2018
+
Birdtalon updated:
+
+
Laser tag ED-209 bots get the correct names upon construction.
+
+
Ty-Omaha updated:
+
+
adds a missing italics tag to nano/templates/song.tmpl
+
+
+
16 September 2018
+
Shazbot updated:
+
+
Adds in the ability to have multiple custom screens.
+
Adds in Lumi's custom faces.
+
+
dandykong updated:
+
+
Internal manipulation surgeries can now be performed on mouths after the head is augmented.
+
+
variableundefined updated:
+
+
Contribution.md now properly state that changelog is mandated for all PR.
+
+
+
14 September 2018
+
Ty-Omaha updated:
+
+
Fixes logic with obscure proc adjust_bodytemperature
+
+
+
11 September 2018
+
Aurorablade updated:
+
+
Adds a missing var to cult comms logging.
+
+
alex-gh updated:
+
+
It is now possible to heal robotic limbs and IPCs through View Variables
+
+
variableundefined updated:
+
+
pAI can no longer use name with special characters that cause their chat messages to disappear.
+
+
+
09 September 2018
+
AffectedArc07 updated:
+
+
You can no longer gib everyone on the server by forcing admins to call verbs with NTSL
+
+
Agameofscones updated:
+
+
removes the equip region for the mask slot on holobadge-cords
+
changes implementation of https://github.com/ParadiseSS13/Paradise/pull/9471 to be smarter and more long term.
+
+
Kyep updated:
+
+
Fixed bad spawn points in the Wizard Academy away mission.
+
The two welding goggles that went missing from the table in atmos have been returned.
+
+
SkeletalElite updated:
+
+
The paper in the holoparasite kit now describes both of the Chaos holoparasite's modes
+
+
Ty-Omaha updated:
+
+
Nightmare writhing now properly works
+
Fixes the wire under the door in med maint that led to a wall
+
Virology now has a hologram
+
+
nicetoolbox updated:
+
+
Prevent instant rev victory in rev gamemode
+
Cryo now heals all your mutated limbs
+
+
uc_guy updated:
+
+
Ghosts can no longer eject IDs from fax machines and ID computers.
+
Fixed exploit that allowed exiled mobs to return to the station
+
+
variableundefined updated:
+
+
One-click antag vampire showing up as a changeling on antag HUD.
+
Claw game should give you token for payment by card properly again.
+
Mime forcewall now properly last for 30 seconds instead of 10.
+
The cancel button actually work properly when editing memory now.
+
A wallet now shows a green card decal by default if there's a card inside.
+
+
+
05 September 2018
+
IrkallaEpsilon updated:
+
+
Adds an attack cooldown on mirrors for all mobs. Yes simple mobs and Xenomorph larvaes included
+
+
variableundefined updated:
+
+
Economy code has been slightly refactored. Report issues.
+
EFTPOS no longer has a name.
+
All date on transaction log should be in long form like "1 January, 2500 22:00:00".
+
Negative number is represented by parentheses in transaction log, positive without (Opposite of before).
+
There's a higher chance of winning $10 in the slot machine now.
+
+
+
04 September 2018
+
Flatty updated:
+
+
Additional icon scaling settings
+
+
FreeStylaLT updated:
+
+
New Kidan sprites and accessories
+
+
IrkallaEpsilon updated:
+
+
Atmos Grenades wont appear in Surplus anymore due to them virtually being unuseable due to OOC reasons in almost any case.
+
+
Kyep updated:
+
+
The power grid in the black market packers away mission has been fixed, and it is no longer possible to effectively skip the entire mission using a crowbar.
+
Lateround blobs now start off as an infected mouse. By moving around/ventcrawling as a mouse, they can find themselves a good nesting area before they turn into a blob core.
+
Meth (and ultra-lube, its equivalent for synthetics) now grant less of a speed bonus.
+
+
Shazbot updated:
+
+
Now you can actually make xeno borgs.
+
+
TDSSS updated:
+
+
Medbelts can now hold hyposprays.
+
+
Tails2091 updated:
+
+
Double welding a closet no longer removes welding tool. format: Changed 0 1 booleans to TRUE FALSE.
+
+
Ty-Omaha updated:
+
+
Secure fridges can be properly emagged
+
Secure fridges can now be EMP'd to override their access requirements
+
+
datlo updated:
+
+
Megaphone now uses the user's speech font (Wingdings/comic sans)
+
+
nicetoolbox updated:
+
+
Fixes Plasmamen wizards not counting as fully garbed
+
+
variableundefined updated:
+
+
Analyzer are now consistently spelled Analyzer instead of Analyser.
+
Hivelord remains send the proper feedback about its preservation method to database.
+
IPC no longer displays their UI / SE in console. Same goes for other invalid subjects. You also can't save their UI / SE anymore.
+
+
+
31 August 2018
+
variableundefined updated:
+
+
Being incapacitated when changing IPC monitor now show a message properly.
+
Borg & AI say actually work properly now. They no longer become whisper.
+
+
+
30 August 2018
+
Alffd updated:
+
+
Fix emote check of can_speak() to only return if the emote produces sound.
+
+
Kyep updated:
+
+
Fixed depot armory shield key not being properly randomized.
+
+
Ty-Omaha updated:
+
+
Decreases sechailer shitcode
+
+
+
29 August 2018
+
Agameofscones updated:
+
+
Removes stray pixel in RD sechud.
+
+
Flatty updated:
+
+
You can now put items on people and take them off while you're riding that sweet, sweet wheelchair.
+
+
Kyep updated:
+
+
Fixed various bugs with spider structures (webs, cocoons, etc), such as them not triggering attack animations, not respecting melee cooldowns, being invulnerable to simple_animals and aliens, etc.
+
+
Superhats updated:
+
+
Adds Meson and Diagnostic HUD implants.
+
ERT equipment has been reviewed by Nanotrasen and changed to more appropriately assist the station when called.
+
Amber Janitor ERT Armor sprite now works.
+
Field Surgery Belt added for Code Amber Medical ERT
+
+
Triiodine (Agameofscones) updated:
+
+
Removed original paramedic EVA sprites
+
Replaced paramedic EVA sprites with medical hardsuit inspired set.
+
Added species variants _(Which did not exist before hand)_ to Unathi, Tajaran, Drask, Skrells, & Vulpkanins.
+
Added the same armor values the basic EVA suit gets (bio 100, rad 20), this puts the paramedic suit in standard with other NT soft suits. edit: Fixed a typo in the santasuit comment, because why not.
+
+
Ty-Omaha updated:
+
+
NT Rep stamp no longer stamps as Central Command, they have their own stamp now.
+
+
variableundefined updated:
+
+
Cutting wires shouldn't cause a runtime error anymore.
+
You cannot bola people without at least two legs (on them) anymore.
+
+
+
28 August 2018
+
Alffd updated:
+
+
Fixes emote code to preform mute checking in the same manner as say code.
+
Adds a new type of muzzle that will shock its wearer when pulsed by an assembly.
+
Adds a new type of voice trigger assembly that is activated by audible emotes.
+
+
Birdtalon updated:
+
+
Fixes torn down posters dropping hypothetical poster when their wall is deconstructed.
+
+
Flatty updated:
+
+
IPCs can also change their screen color in addition to the image now
+
+
Ty-Omaha updated:
+
+
Harm intent attack animations are red instead of white
+
+
taukausanake updated:
+
+
Corrects formatting for the abductor objective messages
+
+
variableundefined updated:
+
+
Logging for prayer.
+
Silicons no longer broadcast their radio message to everyone in hearing range (Only those next to them). Yes, that's a bug, not a feature.
+
+
+
26 August 2018
+
Agameofscones updated:
+
+
Mr. Chang vendor sprite (icon_state: chang).
+
Three new Mr. Chang vendor slogans.
+
+
+
23 August 2018
+
Aurorablade updated:
+
+
Changes to air Subsystem to make it load faster taken from TG by SpaceManiac.
+
Attemps to cap dogs you can cough up to 10..then you cough up a plush fox. Totally normal.
+
+
Birdtalon updated:
+
+
Fixes unexpected item deletion upon changing species.
+
+
Kyep updated:
+
+
Fixed a few bugs (notably, grid check event raising alert level) in the depot.
+
Fixed hand_tele, bluespace tomatoes, etc not respecting the tele_proof flag of areas.
+
+
alex-gh updated:
+
+
Changeling fleshmend no longer overfills their blood.
+
+
variableundefined updated:
+
+
Admin logging for kinetic accelerator.
+
Implantcase no longer disappears when dropped or placed in bag.
+
Logging to borer infestation.
+
A runtime with admin ticket.
+
Defibrillator paddles snap away if you walk away from the defibrillator.
+
Fixes the discard action not displaying who discarded a card from a hand of card
+
Fixes deck of card not being removed properly from your pocket when you drag it over your sprite.
+
+
+
18 August 2018
+
Crazylemon64 updated:
+
+
makes AA's map fix not annihilate every map PR in existence
+
+
+
16 August 2018
+
AffectedArc07 updated:
+
+
Half the scrubbers actually work now
+
+
Birdtalon updated:
+
+
All obj/machinery is now below obj layer.
+
Prevents creation of 0u pills with Chem Master
+
+
+
15 August 2018
+
tlc2013 updated:
+
+
The AutoDrobe now carries a Transylvanian Coat, imported straight from /vg/station for all your Dracula-cosplaying needs. Much like the false Wizard robes, it does nothing for the actual antagonist.
+
+
variableundefined updated:
+
+
Banangarang's medical fluff cyborg's hair colour inconsistency.
+
Comfrey now actually works for healing brute damage.
+
+
+
09 August 2018
+
variableundefined updated:
+
+
banangarang's maid bot fluff sprites
+
+
+
07 August 2018
+
Anasari updated:
+
+
Polaris card system partially ported. Credits to Jedr for the hand of card item_action sprites.
+
+
Kyep updated:
+
+
Simple_animal mobs now get a HUD button that lets them switch between HELP and HARM intents.
+
Replaced the Syndicate Supply Depot with a new version, rebuilt from scratch, that is much more challenging/interesting.
+
It is no longer possible to walk straight through decoy AI cores as if they were not there.
+
Syndicate grenade launcher turrets now actually launch grenades.
+
+
MarsM0nd updated:
+
+
Unathi can now tailwhip when they are supposed to be able to.
+
Tail whipping gets logged.
+
+
+
06 August 2018
+
AffectedArc07 updated:
+
+
Barber no longer spawns with an extra pair of shoes in his bag
+
+
Tails2091 updated:
+
+
Fixed Therapy Dolls not working.
+
Made Prize Machine & Merch Sore readable.
+
Fixed capitalizations and typos in both lists.
+
+
+
05 August 2018
+
Crazylemon64 updated:
+
+
Space ruins can no longer trap you upon border transition
+
There are now several levels of space ruins
+
+
Fox McCloud updated:
+
+
Adds in medical hyposprays
+
+
+
03 August 2018
+
Fox McCloud updated:
+
+
IPC Change monitor is now an action button
+
Slime Color change is now an action button
+
Fixes staff of change leaving behind unknowns
+
Fixes Shadowlings not having shock resistant and thermal vision
+
Fixes staff of change gibbing people
+
+
Shazbot updated:
+
+
Adds in the ability to unsaw sawn off riot shotguns. Change: Changes the riot shotgun icon.
+
+
+
02 August 2018
+
variableundefined updated:
+
+
Nightmares now works. Sleep well.
+
Megaphone actually logs in say log now.
+
+
+
01 August 2018
+
Citinited updated:
+
+
Heaters and freezers now have min and max buttons
+
+
CornMyCob updated:
+
+
The description for miniature energy guns is now accurate
+
The third person text of someone reinforcing an airlock is now accurate
+
+
Tails2091 updated:
+
+
Karma refund now uses switch statement.
+
+
datlo updated:
+
+
Updated syndicate hardsuit description.
+
+
+
31 July 2018
+
Tails2091 updated:
+
+
Claw Game Prize Ball now drops more than one ticket like it should.
+
+
variableundefined updated:
+
+
fix a runtime error with bluespace projector
+
+
+
30 July 2018
+
Tails2091 updated:
+
+
Changed wannabe for loop to a real for loop.
+
+
+
28 July 2018
+
KasparoVy updated:
+
+
You can now safely augment the heads of pointy-snooted Unathi, although your mileage may vary.
+
+
+
27 July 2018
+
AffectedArc07 updated:
+
+
You can no longer use embeds in NTSL
+
+
Crazylemon64 updated:
+
+
Space hotel is back in business
+
Non-hotel SNPCs work again
+
+
Fox McCloud updated:
+
+
Extract posibrains should have the correct names now
+
Abductors can now purchase a mind device to speak into crewmembers minds or give directives to abductees
+
Abductors now have their own versions of the FixOVein, Bonesetter, and Bonegel. Credit to Triiodine for the sprites
+
Adds a new electric shock and chemical gland for abductors
+
viral gland generates random viruses and egg laying gland eggs now have random reagents in them
+
+
variableundefined updated:
+
+
Cyborg Analyzer no longer rounds off the damage number it displays.
+
+
+
25 July 2018
+
variableundefined updated:
+
+
Fixes runtime error from medical kit change
+
+
+
24 July 2018
+
Kyep updated:
+
+
Number of roundstart atmos suits in atmos increased from 2 to 4.
+
+
+
22 July 2018
+
Fox McCloud updated:
+
+
Fixes monkeys not having their own HUD
+
Fixes monkey to human transformations missing their HUD
+
Fixes changing species unequipping items
+
Fixes organs not being rejuvinated properly by mitocholide
+
Fixes shadowlings not being forced to hatch
+
Having a robotic head will allow you to use buzz, ping, beep, and the likes
+
Claw sharpening now works
+
Abductors have their own headset instead of a syndicate one
+
Can put monkeys in the gibber
+
gibbing some species will now generate different types of hides (monkeys give monkey hides, unathi give lizard hides, the likes)
+
fixes Vox name generation based on the wrong syllables
+
consolidates diona name lists; you'll no longer be asked to rename your Diona when you start the shift
+
botany grown diona can no longer rename themselves (as is consistent with ghost roles)
+
Fixes DNA scrambler so it gives a proper randomized species name
+
Fixed an edge case were Vox would have a permanent nitrogen alert
+
Fixes operatives being bald most of the time
+
Adds beesplosion chemical reaction
+
+
and taukausanake updated:
+
+
Swarmers can no longer destroy active clone pods.
+
+
+
17 July 2018
+
Citinited updated:
+
+
volume pumps can be dispensed by the RPD again
+
+
datlo updated:
+
+
Provided abductors with an infection free surgery table.
+
+
+
16 July 2018
+
Citinited updated:
+
+
RPD behaviour has been slightly tweaked - for example you can now rotate / flip / delete individual pipes by clicking on them without affecting other pipes on that tile.
+
+
Fox McCloud updated:
+
+
Fixes hand labelers not being able to label storage objects
+
Cameras can now be destroyed with weapons that have a force of 12 or greater
+
Cameras have 2 wires as opposed to 6; camera focus and power wires still remain
+
You can use hand labelers on reagent containers now
+
+
+
14 July 2018
+
Anasari updated:
+
+
Assuming there is heal left, bandages and ointments used on limbs now heal both the limb and the hand / foot. Bandages and ointments used on the torso now heal head, arms, and lower body. The one on lower body heals the legs too.
+
+
Aurorablade updated:
+
+
Adds Spess Koi and related event.
+
+
Citinited updated:
+
+
The tachyon-doppler array now has a logging interface, and can print off stored explosive logs. Brag to your friends about your bomb-making skills!
+
+
Fox McCloud updated:
+
+
Robotic brains have their own unique sprite and full flavortext's now
+
Fixed a bug where IRC's would have IPC names
+
+
+
11 July 2018
+
Alffd updated:
+
+
Updates SM engine to modern standards
+
Ports SM monitoring system from Bay and TG
+
Adds station wide radiation alarm when crystal/shard goes critical
+
Tesla zapping
+
+
Citinited updated:
+
+
Fortune cookies now drop random fortunes if cooked with a blank piece of paper.
+
+
Fox McCloud updated:
+
+
Adds constructable Integrated Robotic Chassis
+
Adds surgery to customize existing robotic limb appearances
+
Positronic brains renamed to robotic brains
+
+
FreeStylaLT updated:
+
+
Added a Harmonica to Perma Brig
+
+
datlo updated:
+
+
Replaced instances of "Human" in ion laws by "Crew".
+
Fixed the ability of Service Borgs to spawn items on floors. Dosh!
+
+
+
10 July 2018
+
Fox McCloud updated:
+
+
Can no longer take assisted organs at round-start (mechanical organs are still a go, but renamed to cybernetic organs)
+
Can now start the round with cybernetic lungs, liver, and kidneys
+
Can produce cybernetic eyes at R&D and mechfabs
+
Cybernetic internal organs no longer take reduced damage (this does not apply to augments)
+
Cybernetic internal organs can be rendered inoperable (this does not apply to augments)
+
Fixes mitocholide/oculine healing damage on cybernetic organs
+
Fixes being able to restart a dead heart in your hands or with a defib
+
+
+
09 July 2018
+
Fox McCloud updated:
+
+
Enabled augmentation of the head
+
Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; also adds cybernetic upgraded lungs
+
Heads are no longer vital organs, but brains still are
+
+
+
07 July 2018
+
Fox McCloud updated:
+
+
Stechkin pistols in maintenance no longer spawn with a broken magazine
+
+
Kyep updated:
+
+
Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, still exist.
+
+
+
06 July 2018
+
Fox McCloud updated:
+
+
removes explosive lances
+
+
datlo updated:
+
+
Replaced duplicate labor shuttle console on the bridge by a mining shuttle console.
+
+
+
04 July 2018
+
Citinited updated:
+
+
Spelling error in agent IDs
+
+
+
03 July 2018
+
MINIMAN10000 updated:
+
+
Restrained spacepod passanger can now exit pending a 2 minute wait time without moving.
+
+
+
02 July 2018
+
Citinited updated:
+
+
Canisters obey melee cooldown now
+
+
Crazylemon64 updated:
+
+
All MMI variants can now install an "MMI radio upgrade" in order to acquire radio capability when outside of any other chassis. It can be installed either directly on the MMI, or through an opened cyborg chassis. This radio can later be removed if desired by using a screwdriver on the MMI.
+
MMIs can now pull up the direct interface of the radio instead of a single-toggle verb
+
MMI radio control is now done via action button instead of via verb
+
The radio MMI no longer exists as a distinct item
+
+
+
01 July 2018
+
Anasari updated:
+
+
Shuttle can be called at 30:00 instead of 25:00 during War Ops.
+
+
Citinited updated:
+
+
The chef can now process spaghetti into macaroni, and can make several derivative foodstuffs.
+
+
datlo updated:
+
+
Syndicate clowns can now purchase Clown Magboots. Keep honking through slips and atmos!
+
+
monster860 updated:
+
+
Adds the mining podbay (again)
+
+
+
30 June 2018
+
Citinited updated:
+
+
Adds the conveyor belt placer and bluespace conveyor belt placer, allowing you to much more easily create conveyor belts. The former can be gotten at any autolathe, the latter must be researched first.
+
Use a conveyor belt lever on aforementioned item to link all belts inside the placer with that lever.
+
+
+
27 June 2018
+
MINIMAN10000 updated:
+
+
Containment emitters
+
deferred processing of SMES
+
+
+
26 June 2018
+
Alffd updated:
+
+
Additional logic to atmos throwing.
+
+
+
23 June 2018
+
matt81093 updated:
+
+
death squid hitbox position
+
+
+
19 June 2018
+
Anasari updated:
+
+
Gloves of the north star is now categorized under highly visible and dangerous weapon instead of pointless badassery. (Because it's actually good)
+
+
Fox McCloud updated:
+
+
Can cast spells on CentComm z-level during ragin' mages
+
+
MINIMAN10000 updated:
+
+
Cardboard drop counts
+
+
+
17 June 2018
+
Fox McCloud updated:
+
+
Fixes wizards not spawning with their clothes and backpack
+
It no longer snows on away missions
+
+
variableundefined updated:
+
+
Nuclear challenge time limit now depends on round start time.
+
+
+
13 June 2018
+
Aurorablade updated:
+
+
Fluff for Panzerskull
+
+
Fox McCloud updated:
+
+
Medibots now actually talk, like beepsky
+
Adds Plastic surgery; fix someone's face or give them a new identity!
+
Having more than 50 cloneloss will render you "Unknown"
+
head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
+
Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
+
Fixes syndicate medibot not being constructable from tactical medkits
+
Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
+
Radiation event reworked; graphics updated--effects may be a bit more deadly
+
Buffed DIY chainsaws damage slightly
+
You now flip about when you spin with a double e-sword
+
Adds surgical augment to R&D
+
Tools on surgical augment are slightly faster at surgery
+
Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
+
Toxin damage is stealthier and will no longer cause stinging spam message
+
+
Kyep updated:
+
+
Additional job slots are now available at 80+ server population.
+
+
MINIMAN10000 updated:
+
+
Airlock electronics lock
+
Airlock electronics close button
+
+
Piccione updated:
+
+
Added Magboots to the Paramedic's EVA gear closet
+
+
Tayyyyyyy updated:
+
+
Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
+
+
+
11 June 2018
+
FalseIncarnate updated:
+
+
Food on utensils now properly inherits the name of the source dish.
+
Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
+
+
+
09 June 2018
+
Fox McCloud updated:
+
+
Fixes holobarrier icons being missing
+
+
+
08 June 2018
+
Alffd updated:
+
+
Adds an automated emergency var on air alarms for mappers
+
+
Anasari updated:
+
+
Fixes admin log for spray displaying (0,0,0) all the time.
+
+
Desolate updated:
+
+
ED-209 code corrected to work properly. Floorbot code corrected to work properly.
+
+
and Dumbdumb updated:
+
+
Unathi and Vox Sec Hardsuit update
+
+
+
05 June 2018
+
Kyep updated:
+
+
The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe.
+
+
+
04 June 2018
+
Fox McCloud updated:
+
+
Hulk mutation no longer works at range (ie: punching/breaking windows/walls at range)
+
You must be on harm intent to damage things if you have hulk
+
Having hulk allows you to punch and damage just about anything
+
+
uraniummeltdown updated:
+
+
You can smelt titanium and glass together to form titanium glass for building shuttle windows
+
You can smelt titanium, plasma and glass together to form plastitanium glass for building plastitanium windows
+
Fulltile windows now smooth, windows crack as they get damaged and can be repaired with help intent welder
+
Windows have deconstruction hints and show whether they can be rotated or not
+
Plasma glass no longer gets auto-colored
+
RCDs can deconstruct airlocks again, they have no force now though
+
Wielded fireaxe does a lot of damage to windows and grilles instead of just deleting them
+
Glass stacks now use stack recipes instead of a custom menu
+
+
+
31 May 2018
+
FalseIncarnate updated:
+
+
The singulo no longer feeds on attention.
+
+
+
26 May 2018
+
Birdtalon updated:
+
+
Holoparasite guide updated to include newer models. Small tooltip added for charger models.
+
laser tag gun projectiles now play appropriate sound when striking.
+
+
Citinited updated:
+
+
Hopefully fixes all issues with disposals sending you to nullspace.
+
+
Fox McCloud updated:
+
+
Fixes not being able to propel yourself through space by farting if you possessed both superfart and toxic farts
+
+
Kyep and Bxil updated:
+
+
Prevents everyone and their mother from seeing through closed poddoors.
+
+
Tayyyyyyy updated:
+
+
Most things will now use the correct pronouns.
+
Newscasters properly check for feed channel creation and wanted issue creation
+
ERT should deploy properly without admins now.
+
+
+
19 May 2018
+
Aurorablade updated:
+
+
Vet Coat Fluff item.
+
Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling error).
+
+
Fox McCloud updated:
+
+
Adds gloves of the North Star; get them on the uplink for 8 TC
+
Unarmed attacks now have their own icons, as does disarming.
+
Various mobs have their own custom icon attacks
+
Monkies now bite!
+
+
+
18 May 2018
+
Fox McCloud updated:
+
+
Removes engineering and police tape
+
Adds security, atmospheric, and engineering holoprojectors
+
+
tigercat2000 updated:
+
+
You can now lock a facing direction with shift+middle mouse button, or lock your direction towards an object by clicking on it with shift + ctrl + middle mouse button.
+
+
+
15 May 2018
+
Tayyyyyyy updated:
+
+
Pun pun is back!
+
+
+
11 May 2018
+
Kyep updated:
+
+
It is no longer possible to create an infinite number of monkeys from the same monkey cube.
+
+
+
09 May 2018
+
RyanSmake updated:
+
+
You can now jump on fax machines without the UI lying to you.
+
+
+
07 May 2018
+
qwertyquerty updated:
+
+
The window title is custom now!
+
+
+
06 May 2018
+
Kyep updated:
+
+
DeathSquad is now better equipped, and prompts eligible ghosts with a "Do you want to play as DeathSquad?" when called.
+
DeathSquad members (except team leaders) can now choose to spawn as either an organic DS member, or a DS borg.
+
+
+
05 May 2018
+
Tayyyyyyy updated:
+
+
ERT members will have their proper name and appearance when cloned
+
+
+
04 May 2018
+
RyanSmake updated:
+
+
You will now log in to the proper account you input to the ATM instead of the one associated with you.
+
Now ATMs will reconnect after a power outage.
+
+
+
02 May 2018
+
CrazyLemon and Fox McCloud updated:
+
+
Fixes reagent smoke
+
+
+
01 May 2018
+
Alffd updated:
+
+
Tell clients to rejoin after shutdown, before killing the server.
+
+
Fox McCloud updated:
+
+
Removed programmable unloader circuit
+
Bomb testing range can now be utilized multiple times without worry of the bomb bouncing off and returning back to you
+
+
+
30 April 2018
+
Fox McCloud updated:
+
+
Adds Guillotines: make them with plasteel, wood, and cable coil. Execute your comdom head of staff TODAY
+
Clapping now actually plays a clapping sound
+
Adds Blast cannon
+
+
FreeStylaLT updated:
+
+
Medbay treatment center now has a wider entrance
+
Virology hallway is now publically accessible from Surgery waiting room, entrance is now double-doors.
+
+
+
28 April 2018
+
MINIMAN10000 updated:
+
+
Developer express start
+
+
+
26 April 2018
+
Fox McCloud updated:
+
+
Destroys uplink metagaming: Adds in F.R.A.M.E. cartridge
+
using raw telecrystal on an active uplink or yourself will use the entire stack at once
+
can purchase 5 and 20 unit TC bundles from the uplink
+
Removes radio icons when speaking over radio
+
Fixes cargo recycler never recycling items on its own
+
Fixes mech fabricator using an all white UI
+
Can upload alien alloy design to the ORM
+
+
Tayyyyyyy updated:
+
+
You only need to click once to clean a floor
+
+
uraniummeltdown updated:
+
+
Slimes can be injected with plasma reagent and epinephrine to control mutation chance. Plasma increases mutation chance 5% per 5u to a max of 50%, epinephrine decreases by 5% per 5u to a minimum of 0%
+
Slimes can change their face using new emotes
+
Slimes can steal nutrition from other slimes when attacking them
+
Slime docility potion no longer makes a simple animal slime, instead makes the target docile and never hungry
+
+
+
25 April 2018
+
Fox McCloud updated:
+
+
Can make water bottles and caution signs out of plastic sheets
+
Increased cargo plastic sheet count to 50 and reduced cost to 10
+
Adds a recipe for making plastic sheets: oil, acid, and ash
+
Can now make a designs on the circuit imprinter that use metal and other exotic materials
+
Removed the acid cost from most circuit recipes
+
bluespace material requirement on a few parts: bluespace stock parts, phazon parts, bags of holding, and the likes all now require bluespace lattice.
+
Fixes invisible plushies and getting fluff item plushies
+
+
Tayyyyyyy updated:
+
+
You can't see admin character names in PMs
+
+
Xhuis updated:
+
+
The Nanotrasen Meteorology Division has identified the aurora caelus in your sector. If you are lucky, you may get a chance to witness it with your own eyes.
+
+
+
24 April 2018
+
Kluys updated:
+
+
Cleanblots not cleaning /obj/effect/decal/cleanable/trail_holder (blood trails)
+
+
+
17 April 2018
+
Citinited updated:
+
+
Kitchen machinery no longer looks as if it is falling apart.
+
+
MINIMAN10000 updated:
+
+
Adds NOBLUDGEON to door_remote so the remote always triggers
+
Cable coils now allow you to transfer a part of the stack
+
Stack handling from cable.dm is removed as stack.dm already handles it
+
Changed cable coil message
+
The ability to change the color of cables
+
cableColor now follows the new cable_color format
+
+
+
14 April 2018
+
Anticept updated:
+
+
Changed defib timer from 3 minutes to 5 minutes
+
+
MarsM0nd updated:
+
+
Single man up now looks and sounds the same as the global man up for that person.
+
+
+
11 April 2018
+
KasparoVy updated:
+
+
Removes the job-restriction on the purely cosmetic Tajaran veils while those wth integrated HUDs remain unchanged.
+
+
+
08 April 2018
+
Kyep updated:
+
+
Terror Spiders now have a new type in their roster (brown) and see the health status of humanoids (since some of their abilities depend on that status). The Terror Spider away mission has also been adjusted to smooth out areas of no challenge (safe spaces) as well as areas of nigh-impossible challenge (dozens of spiders stacking up together in the final room).
+
+
+
07 April 2018
+
Alffd updated:
+
+
portable (stationary) scrubbers now remove 1/4th as much air per tick at maximum.
+
+
Birdtalon updated:
+
+
Nanocalcium can no longer be synthesised by bees or Odysseus
+
Silicons now have their diagnostic HUD removed correctly.
+
Defibs no longer give endless paddles.
+
Ether re-balanced into a more effective anaesthetic for surgery.
+
Atmos techs have access to tech storage and inner engineering tool room.
+
+
Citinited updated:
+
+
You can't play russian roulette without a head
+
using a russian revolver on another human will now hit them with the revolver instead of failing to play russian roulette with them.
+
+
Crazylemon64 updated:
+
+
Deletion of human mobs now properly deletes equipment balance: Hotel guards now dust on death balance: Hotel guards no longer drop equipment when stunned balance: Hotel guards now are able to use the tasers they hold
+
+
Dyhr updated:
+
+
Agent ID's now provide some presets for valid occupations.
+
+
Kyep updated:
+
+
SIT shuttle can no longer dock in scimaint.
+
Crew demotions and terminations now generate an automatic message to admins. All job changes are also logged.
+
Modular computers now support toggling priority on/off for jobs. The button for doing this in both normal and modular computers is now marked 'Pri', instead of the old '*'.
+
+
MarsM0nd updated:
+
+
Admins can make a fax machine recive the faxes Centcomm or the Syndicate does get.
+
Stops "Unknown" department to send to from coming up when a fax machine gets spawned.
+
Allows adding of departments to send to over a proc-call.
+
+
Spacemanspark updated:
+
+
Mining drones now have movement sprites.
+
+
uraniummeltdown updated:
+
+
Drones will no longer shatter glass tables
+
All small mobs can bump open public access doors
+
+
+
06 April 2018
+
Fox McCloud updated:
+
+
Fixes medical cyborgs having one less stack than they should have they recharge
+
Fixes inconsistency in the medical stacks amounts (they should all be 6)
+
+
+
05 April 2018
+
uraniummeltdown updated:
+
+
Aliens can pull facehuggers out of eggs again
+
+
+
03 April 2018
+
& Deathride58 & Tigercat2000 updated:
+
+
Station time is now randomized [if enabled in game_options configuration].
+
A separate round time has been added to status panel. This will start at 00:00:00.
+
Night shift lighting [if enabled in the same configuration] will activate between station time 7:30 PM and 7:30 AM. This will dim all lights affected, but they will still have the same range.
+
APCs now have an option to set night lighting mode on or off, regardless of time.
+
+
+
02 April 2018
+
Desolate updated:
+
+
New Cricket Borg module selection.
+
+
EldritchSigma updated:
+
+
Mech mounted Disablers are now printable with consistency.
+
+
Fethas updated:
+
+
Viruses Lycancoughy, Adv. Pierrots throat and Kingstons added.
+
+
IK3I updated:
+
+
You can now opt out of the syndicate recruitment semminar prior to boarding the station.
+
+
Kyep updated:
+
+
Syndifox and Syndicat can now do melee damage. Paperwork (cargo sloth pet) no longer can.
+
Syndifox and Syndicat are no longer controllable by players by default.
+
Poly (parrot in Engineering) now knows more phrases.
+
+
Shazbot updated:
+
+
Adds E-pistol crates to the cargo manifest Change: changes the HoP's E-gun to an E-pistol
+
+
Tayyyyyyy updated:
+
+
Borg power warning is on a 2 second cooldown
+
+
+
01 April 2018
+
Tayyyyyyy, LP Spartan updated:
+
+
Once you up to red, it takes 5 minutes before the shuttle transit time is reduced to 5 minutes.
+
+
+
30 March 2018
+
matt81093 updated:
+
+
fish duplication when pulling out multiple fish at once
+
+
+
28 March 2018
+
Birdtalon updated:
+
+
Enforces size limits for placing items inside slicable food
+
+
Fox McCloud updated:
+
+
Nano UI will update a bit faster
+
+
MarsM0nd updated:
+
+
Record printouts now automatically get labled with the name of the person.
+
+
+
25 March 2018
+
Alffd updated:
+
+
Logic checks to lessen death from flying objects due to atmospheric breaches.
+
Removes atmospheric stunning while thrown.
+
+
+
24 March 2018
+
matt81093 updated:
+
+
Borgs no longer keep their special vision when reset with the reset module
+
+
uraniummeltdown updated:
+
+
Deconstructing default RCD airlocks should work now
+
+
+
22 March 2018
+
uraniummeltdown updated:
+
+
Airlocks now have security levels. Secure airlocks cannot be hacked straightaway. Vault doors and highsecurity airlocks have some security by default. You can make an airlock secure by applying metal and plasteel to it while the panel is open
+
As a slime, you can drag yourself onto a target to feed
+
Doors, tables and table frames can be destroyed by hitting them. Airlocks can be repaired by a welder on help intent.
+
You can butcher with any sharp item on harm intent
+
Grilles are stronger
+
Vault door assemblies cost 8 plasteel up from 6
+
Xenomorphs can open non-locked non-welded airlocks after some time
+
Firelocks can be welded open again, firelock [de]construction uses crowbar instead of welder
+
+
+
21 March 2018
+
MarsM0nd updated:
+
+
Xray machines now have xray vision, and check contents of an item, instead of just the item.
+
+
+
20 March 2018
+
MarsM0nd updated:
+
+
Stops a mug from being invisible
+
+
+
19 March 2018
+
Birdtalon updated:
+
+
re-adds the inline "take" shortcut for adminhelps
+
+
Birdtalon, LPSpartan, Shazbot updated:
+
+
Nanocalcium - bone repair reagent. Adds bone repair kit to syndicate uplink containing Nanocalcium autoinjector.
+
+
Fethas updated:
+
+
Vulpkanin, Hunger drain increased slightly. rscadd:Diona now have hair by skittles.
+
Bedsheets can contribute to dream messages.
+
sometimes dreams will be nightmares.
+
Moves dream/nightmare strings to txt files. rscadd:sleeping has a small change to heal brute/fire. but you need a bed..and a bed sheet to be effective.
+
+
Fox McCloud updated:
+
+
Fixes Vulpkanin hunger drain rate being absurd
+
+
IK3I updated:
+
+
Comically sized mugs are slightly less comically sized
+
Lord Singuloth's wrath can no longer be bypassed by baking your input device.
+
+
Shazbot updated:
+
+
Adds an ammo counter to the icon and the in hand icon for the M90-gl
+
Lowers the price of the .357 for nukies
+
+
+
16 March 2018
+
MarsM0nd updated:
+
+
You can now fix broken message monitors
+
+
+
13 March 2018
+
Citinited updated:
+
+
Restricts RPD usage to certain station-side turfs.
+
+
Piccione updated:
+
+
Added marijuana cigarette packets to the Psych's locker.
+
Changed the taste message of a few food items
+
+
+
12 March 2018
+
Fethas updated:
+
+
Full of skittles borg fluff
+
+
+
08 March 2018
+
shazbot updated:
+
+
Fixes up Desolate's name on his other items.
+
+
+
06 March 2018
+
Regen updated:
+
+
Removes the purple hair flower pin from loadout and general player access, because this is a fluff item.
+
+
+
04 March 2018
+
Funce updated:
+
+
APC Interface lock UI works for silicons.
+
+
+
03 March 2018
+
Birdtalon updated:
+
+
A few more items in the Psyche locker.
+
+
Citinited updated:
+
+
IPCs can now lose russian roulette without going to nullspace
+
+
DarkPyrolord updated:
+
+
Sliceable food items are no longer hammerspace capable
+
+
FalseIncarnate updated:
+
+
Adds colored, departmental, and novelty mugs to the hot drinks machine and loadout menu under "Mugs".
+
Adds Head of Staff coffee mugs to their respective lockers.
+
Adds support for inserting items into vendors and having the vendor interact with said item when vending items.
+
Adds the ability to insert containers into the hot drink machine, filling the container with your purchase.
+
+
Fethas updated:
+
+
The booze o' mat now has wine..bags.
+
+
KasparoVy updated:
+
+
The eyes of humanoids who have XRAY vision mutation, sufficiently high darkview, synthetic eyes or eye implants now appear to shine in the dark.
+
Adds a way to 'cut' one icon's pixels out of another by using the get_icon_difference() proc.
+
get_location_accessible() now checks the appropriate flags when determining the accessibility of eyes.
+
+
Serket updated:
+
+
Death Wand can kill slimes and hopefully everything
+
Wizards can no longer mind-swap borgs
+
ERT Specops Office now comes with extra privacy (borgs can't open the ERT mech room, etc.)
+
Removed snow from Mr Chang's
+
Fixed a dethralling error causing message typos
+
+
Tayyyyyyy updated:
+
+
AIs can view info of their synced borgs in the status panel
+
+
+
26 February 2018
+
Birdtalon updated:
+
+
Removes printing photos on security consoles.
+
+
+
21 February 2018
+
uraniummeltdown updated:
+
+
Added titanium and plastitanium. Mine the asteroid for titanium, make plastitanium by smelting together titanium and plasma
+
You can build shuttle floors and walls with titanium and plastitanium. Can also make shuttle airlocks by applying titanium to a non-mineral airlock
+
Shuttle windows have explosion resistance now
+
A few RnD recipes require titanium now
+
+
+
20 February 2018
+
Alffd updated:
+
+
Reduce all atmospheric stuns by 80%
+
Cap the maximum atmospheric stun time to 4 seconds
+
+
Anasari updated:
+
+
Add paperplane. Alt-click or use a verb on a piece of paper in your hand to make them.
+
+
Birdtalon updated:
+
+
adds [time] tag for paperwork
+
+
Citinited updated:
+
+
You can now roll up flags.
+
+
Fox McCloud updated:
+
+
Adds in a Dance Machine
+
IEDs now have a blast radius again
+
Slap crafting of IEDs is gone; use personal crafting instead
+
+
HugoLuman updated:
+
+
coughing and sneezing sounds for the Drask
+
+
MarcellusPye updated:
+
+
Grays can now drink sulphuric acid without being burnt
+
+
Shazbot updated:
+
+
Fixes Patch's patch
+
+
Tayyyyyyy, bryanayalalugo updated:
+
+
News reporters can now add titles to their stories!
+
+
+
05 February 2018
+
IK3I updated:
+
+
Next gen dining is now available at your local autolathe!
+
+
MarsM0nd updated:
+
+
Pod lock busters can now unlock pods
+
Pods can only be locked with a locking system installed.
+
+
Tayyyyyyy updated:
+
+
Energy swords, energy daggers, energy cutlasses, and energy axes emit light. Toy versions do not.
+
+
uraniummeltdown updated:
+
+
Multitile airlock opening/closing animation is no longer glitchy and paper/photos don't float in the air when opening/closing them
+
+
+
02 February 2018
+
Fethas updated:
+
+
TG Port, ais now have an advanced diagnostic hud that lets them see the path a bot is taking.
+
Bots get access for 60 seconds to all doors to get to thier locations. rscadd:Pai controlled bots will get a notification they are being called. rscadd:all living mobs now can have a med hud.
+
+
+
01 February 2018
+
Squirgenheimer updated:
+
+
Using the 'tear reality' rune as cult should now be punished when the invokers do not have the god summoning objective
+
+
Tayyyyyyy updated:
+
+
Players job banned from syndicate can no longer play emagged drones
+
+
uraniummeltdown updated:
+
+
Examining an airlock assembly gives construction hints and shows what pen name is set. Mineral airlocks can have glass added to them.
+
Added public and external maintenance airlock assemblies to metal recipes
+
Maintenance, standard and external airlocks now have glass versions. Multi-tile airlock has a solid version.
+
Added more airlocks to RCD
+
You can attach paper and photos to airlocks, wirecutters to remove them
+
Airlocks open faster
+
Vault and high-security airlocks are made with 6 plasteel up from 4
+
Plasteel should have the correct amount of materials in it now
+
+
+
29 January 2018
+
Fox McCloud updated:
+
+
Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area
+
+
MarcellusPye updated:
+
+
Changes the ghost preferences section of game preferences to display the currently active option instead of the inactive option.
+
+
+
27 January 2018
+
IK3I updated:
+
+
Saving a chat log no longer hangs you.
+
+
uraniummeltdown updated:
+
+
Client FPS setting should save properly now
+
+
+
26 January 2018
+
tigercat2000 updated:
+
+
Insta-movement works marginally better
+
+
uraniummeltdown updated:
+
+
You can now change your client FPS in Game Preferences
+
+
+
24 January 2018
+
IK3I updated:
+
+
Cancel means Cancel on admeme console reports!
+
When eldritch gods, demons, handsy aliens, and incarnations of darkness tell you it's time to go, you go
+
Comms Console will tell you when the shuttle can't be recalled
+
Admemes can now designate whether a shuttle they call is recallable
+
Admemes can exercise their power to recall any shuttle, even in defiance of spooky ghosts!
+
+
Kyep updated:
+
+
Added config option to limit the amount of time shadowlings can remain unhatched before they start getting pushed to hatch.
+
+
Tayyyyyyy updated:
+
+
Energy beams of all types emit light.
+
Flashbangs emit a burst of light when detonated
+
+
+
21 January 2018
+
KasparoVy updated:
+
+
Avoids wanton bloodshed by revising logic that checks for blood already in the splat zone.
+
Adds a helper proc with which you can get a list of all atoms of a type at a given location.
+
+
Tayyyyyyy updated:
+
+
Due to increasing amounts of spaghetti code in the cryptographic sequencer, emagging maintenance drones cripples their table pathfinding and removes their ability to pathfind under people's legs. Also, Nanotrasen has patched its drones to remove the hidden diamond drill module and rewritten its drone control code so that drones that don't call home and verify their programming after a certain amount of time are destroyed automatically.
+
+
+
20 January 2018
+
uraniummeltdown updated:
+
+
Fixed issues with ethereal jaunt directions, wraith jaunt no longer shows the wizard effects
+
Guardians phasing in/out will properly show a little animation
+
The petting heart animation is smoother
+
+
+
19 January 2018
+
Citinited updated:
+
+
Using a syndicate balloon while it's in your hand allows you to play with it.
+
+
uraniummeltdown updated:
+
+
Wooden holodeck table sprites show up properly
+
Table construction has been changed a bit, apply stack items (carpet, metal, glass, wood) to table frames to build tables instead of using table parts.
+
Slightly increased the health of racks and tables with low health
+
Holodeck tables will now smooth with one another
+
Holodeck tables and racks can be interacted with in more ways
+
+
+
13 January 2018
+
Citinited updated:
+
+
The ocean and the pool are no longer colder than outer space.
+
Water now cools or heats you gradually, not all at once.
+
+
Kyep updated:
+
+
Refactored Paranormal/Janitor dress code, and Cyborg ERT spawn code.
+
Signing up for ERT, then going AFK, such that your AFKness prevents you and/or others spawning as ERT within a reasonable (2 minute) period of time, now generates a warning to online admins.
+
+
+
11 January 2018
+
Bxil updated:
+
+
Economy accounts now use the correct date.
+
+
Citinited updated:
+
+
Jaunters work again.
+
+
Jountax updated:
+
+
Fancy shoes no longer cost one's entire loadout.
+
Sugarcane added to the MegaSeed Servitor. No more garden raids!
+
+
Kyep updated:
+
+
Department management (aka: demotion) consoles only worked for their respective head of staff. Captains, CC characters, etc could not use them.
+
Fixed two brown wooden doors in wizard academy away mission which had space turfs under them, leading to nasty results with fastmos.
+
Added deathsquid.
+
Further modified construction site layout, fixing various issues and making it easier to test new engine setups there.
+
+
Tayyyyyyy, FPK updated:
+
+
The more dark view you have, the more eye damage you take from flashing. Darkness amplifies this effect.
+
+
uraniummeltdown updated:
+
+
Freezers and other atmos machines will drop frame and parts correctly again
+
+
+
07 January 2018
+
Kyep updated:
+
+
All mineral floor tiles no longer incorrectly show up as abductor flooring.
+
+
+
05 January 2018
+
Kyep updated:
+
+
Improved wild west away mission. Fixes issues such as lack of magboots, and 'projectile gun's appearing. Adds some flavor items (syndie soap in shower, medkits in storage). Also adds syndie comms device which alters the mission depending on how it is used.
+
+
uraniummeltdown updated:
+
+
Construct shells have a new sprite
+
+
+
04 January 2018
+
Anasari updated:
+
+
A lot of underused nuke op items made cheaper.
+
Syndicate hardsuit removed from nuke op because you already got one free.
+
Tactical medkit give you four synthflesh patch, no more stetho or lethal syringe.
+
RSG added to nuke op uplink. Dart gun no longer available.
+
+
+
31 December 2017
+
Alffd updated:
+
+
Wire panels are now effected by the colorblindness disability
+
Wire panel color changes now support RGB hex values
+
+
Fox McCloud updated:
+
+
Fixes arm implants being immune to EMPs.
+
+
FreeStylaLT updated:
+
+
A dedicated toxic pill sprite, Cyanide and Toxin pills now use it by default.
+
+
KasparoVy updated:
+
+
Blood splattered by projectiles hitting a mob now land one tile away in the direction of the splatter graphic. Blood splattered on walls/windows/etc. can be cleaned off with soap.
+
Xeno-blood splatter is now the appropriate colour.
+
+
Kyep updated:
+
+
IAAs now require 10h of playtime, instead of 5h, to unlock. The IAA job's alt title is now "Human Resources Agent" instead of "Lawyer" or "Public Defender". IAAs now start with basic access to all departments (sci/med/cargo/eng), so that they can more easily conduct investigations. Overall, their role has been clarified, to be explicitly on the side of NT, not simply that of defendants. Further, they're empowered to, and expected to, actually conduct investigations, and generally be better at their jobs.
+
The mech bay next to Robotics now has a robotic storage unit (cryopod for cyborgs).
+
The Construction Site (partially finished space station east of eng outpost) has been revamped. With basic power/atmos networks in place, it should now be much more viable to repair it during a round.
+
Added shutters to specops office next to ERT spawn. This prevents borgs remotely activating the admin-only buttons in that office.
+
+
Tayyyyyyy updated:
+
+
Crew pinpointers no longer lose signal when the target enters something like a sleeper or a mech
+
+
Vivalas updated:
+
+
It is now possible to directly inject spaceacillin into organs during surgery, and it only uses 5u to completely cleanse the organ,
+
+
+
27 December 2017
+
Tayyyyyyy updated:
+
+
Repeated lines are now combined in the chat window. This can be disabled in chat window preferences.
+
Paramedic, Blueshield, and Medivends get crew pinpointers
+
+
+
23 December 2017
+
Fethas updated:
+
+
Borers can no longer be possesed by ghosts using an antag hud.
+
+
Fox McCloud updated:
+
+
Having a master, as a spider means you actually get a message who is your master now
+
+
Purpose2 updated:
+
+
Cartographers dispatched. NanoUI Minimap is now updated.
+
+
Santa's Lawyer updated:
+
+
Removed riot dart toys from under Christmas trees.
+
+
+
21 December 2017
+
FalseIncarnate updated:
+
+
Adds fans under the doors at the North Pole.
+
+
Purpose2 updated:
+
+
You may no longer use strikethroughs/italics in OOC. This was causing backend server problems due to how shoddily BYOND is coded, and cannot be safely added right now.
+
+
+
19 December 2017
+
Santa Claus updated:
+
+
Christmas cheer!
+
Grinch
+
missing emergency nitrogen / plasma tanks
+
+
+
15 December 2017
+
uraniummeltdown updated:
+
+
Plants no longer take twice as many cycles to age
+
+
+
05 December 2017
+
Kyep updated:
+
+
Removed peacekeeper borgs.
+
+
+
04 December 2017
+
Tayyyyyyy updated:
+
+
IPCs no longer vomit next to rotting bodies
+
+
Terillia updated:
+
+
Fixes the litch Hat and Sandals
+
+
+
02 December 2017
+
uraniummeltdown updated:
+
+
You can now create vault door assemblies with 4 plasteel sheets
+
Science airlocks have been added to metal recipes and the RCD
+
Airtight and Maintenance Hatch added to the RCD
+
Highsecurity airlock assemblies are built with 4 plasteel instead of 4 metal
+
All doors and doorlike things (firelock, airlock, windoor, blast door, shutters, spacepod door) run off the Environment Power Channel
+
Emagged airlocks have a different description on examining
+
Screwdrivering an airlock now displays a message. No more guessing if the panel is open or not.
+
Cult airlocks will keep their old name on being converted.
+
+
+
01 December 2017
+
Fox McCloud updated:
+
+
Lungs are now responsible for breathing instead of a mob; mix and match lungs however you like!
+
Ripping out someone's lungs or them necrotizing will make a person suffocate; it will no longer kill them instantly
+
Drask no longer heal burn damage from breathing cold air (brute is still healed)
+
Lungs no longer rupture in low pressure
+
Not having lungs means you can't talk
+
remove the discrete internals button on the HUD; use the tank action button!
+
Fixes slimes dying by themselves
+
+
+
30 November 2017
+
ExitGame updated:
+
+
vox quill rustle emote
+
species check
+
+
Fox McCloud updated:
+
+
shotgun pellets deal less damage the further they travel
+
+
+
28 November 2017
+
Kyep updated:
+
+
It is no longer possible for Service borgs using the Rapid Service Fabricator to end up with negative energy.
+
+
+
27 November 2017
+
uraniummeltdown updated:
+
+
Composting plants/pills into hydroponics trays transfers all reagents
+
+
+
26 November 2017
+
FalseIncarnate updated:
+
+
The Syndicate has determined that subtle and stealthy items don't benefit from obvious names, and thus have rebranded their contortionist jumpsuit to something less eye-catching.
+
The Syndicate decided to be less stingy than Nanotrasen and made the contortionist jumpsuit out of flame resistant materials. You may burn, but the jumpsuit won't!
+
+
Fethas updated:
+
+
Penguins, Penguins in shambreos and Albino penguins are a thing.
+
+
Fox McCloud updated:
+
+
Fixes being able to recall Abductor-called shuttles
+
Fixes slime transformation potion not making you a real slime
+
Polymorph slimes are now random color
+
+
Jountax updated:
+
+
Can now add laceup shoes to your loadout.
+
+
Kyep updated:
+
+
Service borgs are now able to dispense a variety of fruit juices, as well as coffee and tea. Additionally, they can use a health scanner on crew, and the poisoned beer they get from being emagged is much more deadly. They can also create snackfood using their Rapid Service Fabricator.
+
When an admin creates a classified message manually, and selects 'no' to the 'notify crew' option, the incoming message will be announced via command radio, instead of a priority announcement that the whole crew sees.
+
ERT borgs can now speak on ERT radio, even after choosing a module.
+
ERT borgs are now always named as such, may only take modules that would be useful in an emergency, and always have their emagged modules unlocked. They also have an 80% chance to resist emagging their cover lock, so you will need to stun them with a flash before trying to emag them.
+
+
MarsM0nd updated:
+
+
Logs usage of stun talismans.
+
Stops rigsuits from shocking over distance.
+
Let's malfunction count down while not being actively worn, to avoid permanetly breaking it.
+
Allows boots to be worn under rigsuit boots.
+
Wirenames for the rigsuit wires if you can see them.
+
Rigsuits only slow you down when deployed, potentially less if active.
+
+
Ty-Omaha updated:
+
+
Gambling machines now payout again.
+
+
uraniummeltdown updated:
+
+
Particle effects pass over tables and grilles
+
Nanofrost smoke fading out actually works now
+
All smokes now fade out
+
Nanofrost smoke can now also weld scrubbers
+
+
+
22 November 2017
+
Fox McCloud updated:
+
+
"Pick Up" from right clicking obeying the same rules as regularly clicking on it
+
+
+
19 November 2017
+
Fox McCloud updated:
+
+
Fixes cult shuttle curse from being used more than twice and from extending shuttle call duration once nar-sie has been called/slaughter demons have been called.
+
+
+
18 November 2017
+
MarsM0nd updated:
+
+
A (possibly non-existant) officer's beret does no longer incorrectly hide hair.
+
+
+
13 November 2017
+
Alffd updated:
+
+
Fixes muzzles not preventing vampire biting unless the target was wearing the muzzle.
+
Makes throwing the ambulance with atmospherics almost impossible.
+
+
VexingRaven updated:
+
+
Fixes the message that appears when a mob being force-fed a snack finishes eating that snack.
+
+
+
12 November 2017
+
Kyep updated:
+
+
It is now much harder for Command/HoS to get away with illegal executions. Admins are far more likely to notice people being set to execute, more detailed explanations of executions must be sent to CC, and admins are more able to intervene when an execution is obviously illegal.
+
+
+
11 November 2017
+
FalseIncarnate updated:
+
+
Full windows are now 100% stronger than before, so you don't have to pick strength over security.
+
Full windows now take longer to deconstruct so they offer slightly better security against break-ins. Toolspeed does apply.
+
Full and directional windows can be built on grilles now, and you can even pick the direction! Technically both a tweak and an addition...
+
+
+
10 November 2017
+
Allfd updated:
+
+
A new Anti-Bite muzzle has been added to the SecVendor. This muzzle can be locked through the strip panel and will prevent a vampire from feeding.
+
Holy water now causes vampires to vomit blood, before vomiting the water. After this holywater behaves as normal.
+
+
Anasari updated:
+
+
79 hairstyles ported from Polaris.
+
+
+
05 November 2017
+
Fethas updated:
+
+
changes the my tickets from a verb..to a prock. To quote lemons: F.
+
+
KasparoVy updated:
+
+
The Barber's dye bottle now works again.
+
The Barber's dye bottle can now colour alternate (facial) hair themes where applicable.
+
+
+
04 November 2017
+
FalseIncarnate updated:
+
+
MANDATORY FUN! Arcades added to both stations!
+
Bottler units have been spotted on board both stations!
+
Arcade carpet tiles added to the prize counter for 150 tickets (credit to Goonstation for the turf icon).
+
Cyberiad bathrooms should have 100% fewer floating showers (behind curtains).
+
Showers have been fitted with mist-reducing showerheads. They should no longer generate infinite mist if rapidly toggled.
+
Cyberiad chemistry has had the extra APC removed. Now they only have one as standard.
+
+
FreeStylaLT updated:
+
+
Medbay has been remapped
+
New Maint areas have been added south of Medbay.
+
+
+
01 November 2017
+
FreeStylaLT updated:
+
+
Medbay has been remapped
+
New Maint areas have been added south of Medbay.
+
+
Kyep updated:
+
+
Freedom Operative suits no longer revert to a normal red syndi suit icon when you use their 'toggle hardsuit mode' option.
+
+
MarsM0nd updated:
+
+
Stops holograms from attempting to appear when they just disappeared because the AI became unable to keep it up.
+
+
+
30 October 2017
+
NewSta updated:
+
+
There is now a "GitHub" button.
+
Modified the height of the "Donate" button to make it equal to that of other buttons.
+
The distance between the info and wiki buttons is now 30 px. All other buttons now have a 5px distance between them.
+
Fixed a typo in the wiki window.
+
+
+
29 October 2017
+
Alffd updated:
+
+
Ion Rifles are no longer pistols
+
+
+
28 October 2017
+
Anasari updated:
+
+
Some underappreciated traitor items had been made cheaper.
+
+
Kyep updated:
+
+
Vamp jaunt/shadowstep no longer works on z2.
+
Ghosts with sec hud enabled can now see mindshield, tracker and chem implants, as well as wanted status.
+
+
Landerlow updated:
+
+
Adds Sake to a hacked booze dispenser's menu.
+
+
Squirgenheimer updated:
+
+
Fixed a typo causing the inability to create the large energy crossbow in the protolathe.
+
+
+
27 October 2017
+
Birdtalon updated:
+
+
Birdtickets: Adminhelp Ticketing System
+
+
FalseIncarnate updated:
+
+
Silver Slime Core reactions can only summon forth drinks that actually contain a drink. Begone thirst!
+
Removes some "unsafe" chemicals from lists of potential chemicals for inclusion in things like random pills or bottles, added one to replace them.
+
Removes adminordrazine and nanites from vent clog, replaces nanites with syndicate_nanites.
+
+
+
26 October 2017
+
Anasari updated:
+
+
Change some brain damage phrases. Add a lot of new one.
+
+
FreeStylaLT updated:
+
+
Moves Ambulance's key to Paramedic's EVA locker from his clothing locker
+
Removed an unnecessary EVA helmet from Paramedic's EVA locker
+
+
Kyep updated:
+
+
Soviets (including Soviet Tourists, a non-antag filler role) no longer get all-access to the Cyberiad when they visit.
+
Freedom Operatives are now a support outfit that admins can equip players as.
+
+
TDSSS updated:
+
+
Added a shortcut to talk on ERT channel, namely ':$', bringing it in line with other channels.
+
+
+
25 October 2017
+
Anasari updated:
+
+
Flavour text description in character setup now consistent with rules.
+
Grenade reagent are also logged when they are primed
+
TC from war op increased by 2 per player above 50.
+
+
Kyep updated:
+
+
ERTs now support janitor, paranormal, and cyborg ERT units, as well as specific slot configurations.
+
Heads of staff who are editing another admin's permissions in the admin panel can now toggle several permissions for a person without re-finding them in the list. Hitting 'cancel' at any point drops out of the loop. It also notifies admins whether they're toggling a permission on, or off.
+
ERT spawn area now shows ERT request reasons, and admins can enable the use of a teleporter or grav catapult without mechs.
+
+
+
22 October 2017
+
Crazylemon64 updated:
+
+
Suiciding crewmembers are no longer capable of being cloned.
+
+
Fethas updated:
+
+
makes a better proc for doing spins (IE Ian chasing tail, etc) then was previous.
+
+
McCloud and Alffd updated:
+
+
Merge all LINDA and atmos machine functions into the air controller subprocess.
+
Air alarms in scrubbing mode will shut off when alarm enters danger state. If this occurs simultaneously with a max2 temperature alarm panic siphon will automatically activate.
+
High air pressure differences will throw objects and knock over station species.
+
Add magpulse to syndicate and death squad borgs.
+
Change all volume pumps to regular pumps in atmospherics to accommodate new LINDA speeds.
+
Change LINDA interval from 2 seconds to 400 milliseconds.
+
Removed unused control from flamethrower.
+
Set flamethrower release equal to fuel used.
+
Increased Reinforced Wall HP from 200 to 600.
+
Buff aliens against space wind.
+
Buff Terror Spiders against space wind.
+
Buff some blobmobs aginst space wind.
+
Frost requires heat to remove.
+
+
+
15 October 2017
+
Citinited updated:
+
+
Clipboards now have more functionality. You can now stamp them, attach paper bundles to them, write on any contained paper by clicking on the paper's name using a pen, add pens directly to them, and rearrange what piece of paper is on top!
+
Full-sized plasma windows are fire-resistant, and full-sized reinforced windows are fully fireproof.
+
You can now remove facehuggers from corgis. Corgis that have been glomped by multiple facehuggers will now work as you'd expect them to.
+
Radiation mines no longer change the DNA of species that don't have it.
+
Firedoors and other doors will no longer close when a shuttle docks. Open firelocks can no longer be welded. Welded firelocks should no longer open under any circumstances.
+
Open airlocks no longer spark when you throw something conductive through them.
+
+
Fethas updated:
+
+
Many things use sleeping. Surgry pain fail fix.
+
+
Imsxz updated:
+
+
Ballistic mech weapons now all use the ammo system
+
+
Kyep updated:
+
+
Changing someone's sec status now prompts for a reason. The change, and the (optional) reason for it, is written to that person's sec record, and to the server logs. This applies to changes made by sec HUDs, and by records computers.
+
Magistrate/Captain/HoS/Warden can now use a sec records computer to set a person to "Execute" status. This status cannot be unset by HUDs, and broadcasts a notification to all online admins when it is set. It is intended to replace the "fax CC" requirement for executions. Persons with this status show up with a white 'X' as their sec hud icon.
+
+
TullyBurnalot updated:
+
+
Shadowlings are extinguished after hatching, allowing Plasmamen Shadowlings to not burn to death.
+
Shadowlings now passively heal eye damage, eye blurriness
+
+
Vivalas updated:
+
+
Splints now pop off after 2000 steps, or when taking a lot of damage to that limb. Getting surgery for those broken limbs might be a good idea now.
+
+
+
14 October 2017
+
Anasari updated:
+
+
Explosive lance doesn't embed anymore.
+
+
Fethas updated:
+
+
ARMBANDS! REPRESENT! SEE THE LOADOUT!
+
+
Kyep updated:
+
+
HoPs/Captains opening/closing job slots is now announced to admins. No more HoPs opening 30 clown slots without admins noticing.
+
+
MarsM0nd updated:
+
+
Gives a choice whether to mangle black gloves, or to completely cut of the fingertips
+
+
+
11 October 2017
+
Anasari updated:
+
+
Slot machine no longer earn money on average. Bet changed to 100.
+
All items can be used to smash windows instead of only those defined as weapons. (e.g. including guitar & flashlight)
+
Mulebot with pAI cannot knock people down anymore.
+
+
Birdtalon updated:
+
+
Terror spiders now respect antagHUD respawn restrictions.
+
+
Kyep updated:
+
+
mindslaving an antagbanned player now offers control of their mob to ghosts.
+
+
TullyBurnalot updated:
+
+
Can now place garbage in garbage cans without standing on top of them.
+
+
scrubmcnoob updated:
+
+
Cult must use teleport tailsman in active hands.
+
+
uraniummeltdown updated:
+
+
New PACMAN portable generator sprites
+
+
+
10 October 2017
+
Birdtalon updated:
+
+
Bees with no reagent will now work.
+
+
+
07 October 2017
+
Birdtalon updated:
+
+
User interface tweaks to Brig timers.
+
Seconds converted to minutes and seconds in Brig radio and security console printouts.
+
Bees can no longer reproduce un-synthable reagents.
+
+
imsxz updated:
+
+
Aliens now always spawn as a pair when their infestation event begins.
+
+
scrubmcnoob updated:
+
+
Abductors can no longer use megaphones.
+
+
uraniummeltdown updated:
+
+
Adds new sprites to the unused and used eldritch whetstones. Sprites by Fury McFlurry.
+
Air tanks now have their own sprite, no longer looking like oxygen tanks
+
10mm alt magazines have their own sprites
+
+
+
06 October 2017
+
Birdtalon updated:
+
+
Bottler doesn't break after one use.
+
+
+
05 October 2017
+
Birdtalon updated:
+
+
Re-adds missing light switch to robotics.
+
+
+
02 October 2017
+
Imsxz updated:
+
+
Rapid re-hatch no longer kills shadowlings.
+
Vampires can no longer enthrall chaplains
+
+
+
30 September 2017
+
Jovaniph updated:
+
+
Coroner now has their own locker in the morgue.
+
+
Landerlow updated:
+
+
Adds hydrocodone to the Cyborg Hypospray
+
+
+
29 September 2017
+
Citinited updated:
+
+
Telescreens and entertainment consoles now have 'off' and 'broken' sprites.
+
Wooden TVs, engineering camera consoles, mining camera consoles, telescreens, and entertainment consoles now have their own circuit boards and can be reconstructed!
+
Using a multitool on a telescreen or entertainment monitor will now allow you to reposition it.
+
+
imsxz updated:
+
+
Subtle messages no longer begin with "old"
+
+
+
28 September 2017
+
MarsM0nd updated:
+
+
Stops the electrified arm from combat and stunbaton implant from runtiming.
+
+
uraniummeltdown updated:
+
+
Changelings have a new power, Biodegrade, for 2 evolution points. For 30 chemicals you can vomit acid onto restraints, welded/locked lockers and spider cocoons to escape them.
+
Hivemind Link for changelings has been readded, it was removed in error
+
+
+
05 September 2017
+
Kyep updated:
+
+
Adds alternative military shuttle, NT Navy troop transport.
+
+
+
04 September 2017
+
Kyep updated:
+
+
Admins under the effects of 'invisimin' no longer show up on sec huds, medical huds, etc.
+
+
+
03 September 2017
+
Birdtalon updated:
+
+
Flip emote has a small chance of a failure and 100% chance of embarrassing yourself.
+
+
Citinited updated:
+
+
You can now deconstruct the indestructible stool in the old bar's back room.
+
Security and bar maintenance airlocks are now decoupled.
+
The air vent at the fore of AI satellite now starts turned on.
+
Engineering equipment now only has one air vent, not three.
+
Added a missing bit of plating underneath the engineering shuttle's window.
+
Added a missing scrubbers pipe in Central Primary.
+
The camera and light fixture in the prisoner transfer centre are now wall-mounted instead of being attached to the blast doors.
+
Adds the Flaming Moe cocktail.
+
Shot glasses can now be set alight using something hot.
+
+
+
02 September 2017
+
Landerlow updated:
+
+
Adds a recipe to create enzymes to cook with.
+
+
+
01 September 2017
+
Birdtalon updated:
+
+
Fixed small bug with wall lockers not respecting distance.
+
+
+
28 August 2017
+
Birdtalon updated:
+
+
Replaces civilian door remote in the Head of Personnel locker with a brand new remote with additional access to better suit the Head of Personnel's responsibilities.
+
Nanotrasen Mining Bots are no longer safe from EMPs.
+
Syndicate bee-case sound now only plays locally when opened.
+
You can open wall lockers with control click.
+
+
Birdtalon & Hylocereus updated:
+
+
Adds pineapples which can be grown in hydroponics, juiced or sliced and made into hawaiian pizza.
+
Adds hawaiian pizza to the pizza crate.
+
+
Fethas updated:
+
+
The cultist dagger has had its special removed, it still cuases small bleed and retains its embed chance.
+
Prayers now dsiplay the diety set by chaplains (if any) to admins in prayers, or eldergod if a cultist. Prayers are purple for normies, Red for cultist and blue for chaplains
+
+
Fox McCloud updated:
+
+
IPCs can now be dissected by adbudctors
+
+
Fox Mccloud updated:
+
+
Adds an accordian, glockenspiel, harmonica, recorder, saxaphone, trombone, xylophone, bikehorn, and piano synthesizer
+
pick up a big band supply pack of instruments at cargo for 50 supply points
+
+
Jovaniph updated:
+
+
Holodeck Energy Swords sound was change to simulate being attacked by a real energy sword.
+
+
Landerlow updated:
+
+
Adds six additional roundstart disabilities to choose from
+
+
matt81093 updated:
+
+
robot analyzer to medical module cyborgs for IPC diagnosing
+
+
+
24 August 2017
+
Birdtalon updated:
+
+
Cultist structures can now be destroyed using melee and or projectiles
+
+
Fox McCloud updated:
+
+
Fixes Diona, Plasmamen, and other races having internal bleeding
+
+
+
16 August 2017
+
Citinited updated:
+
+
Adds the plasmaman flag; credit to Shadeykins for the original sprite! Buy it at the merch store and show your superiority over other, less flammable, species!
+
All flags should now have in-hand sprites.
+
Burning a flag while it is in your hand will now update your mob's sprite.
+
Fixes another issue with disposals sending things to nullspace.
+
+
Fethas updated:
+
+
Swarmers can now deconstruct simply by clicking, ctrl click to teleport.
+
you can now deactivate depowered swarmers with a screwdriver.
+
Swarmers can now consume swarmer shells for a refund.
+
swarmer lights are cyan.
+
+
Fox McCloud updated:
+
+
Cluwning is far more difficult to remove
+
Cluwne mask cannot be melted with acid
+
Cluwne suit has no sensors
+
+
Kyep updated:
+
+
Admins now have a 'List SSDs' verb to list SSD players, and the ability to move them to cryo.
+
+
+
15 August 2017
+
Birdtalon updated:
+
+
Medbots can now inject from their internal beakers.
+
Swarmers can no longer kill the AI with direct attacks.
+
Simple animal melee damage now has a sanity check for AI core.
+
+
+
14 August 2017
+
AndrewMontagne updated:
+
+
Modular computers now print fields correctly.
+
Files on modular computers no longer vanish shortly after editing.
+
Modular computers printers now make printing noises.
+
You can no longer try and buy a tablet with a printer.
+
Cloning a file now works.
+
+
Birdtalon updated:
+
+
Spiderbots can now pass tables, making their Hide worthwhile.
+
Fixes interactions with cargo crates.
+
+
Citinited updated:
+
+
Nanotrasen's legal department clamped down on video cameras being misappropriated by crew, and as such cameras are now unable to broadcast from beyond the gateway.
+
+
Fethas updated:
+
+
Dethaws some IPC surgery issues.
+
+
taukausanake updated:
+
+
Adds an Atmospherics duffel bag that is yellow and blue
+
Adds sub-department colors to medical duffel bags and purple to Science duffel bags
+
Captain's lefthand west sprite corrected
+
+
+
10 August 2017
+
KasparoVy updated:
+
+
Blood trails are now the same colour as the blood pools they came from when viewed by colour blind or noir shades wearing humanoids.
+
+
+
09 August 2017
+
Purpose2 updated:
+
+
Adds a cycling airlock on the new mining mini outpost.
+
Re-adds the cycling airlock on mining outpost.
+
Fixes the broken atmos piping on mining outpost.
+
Fixes a lack of lighting on mining outpost.
+
+
+
06 August 2017
+
Birdtalon updated:
+
+
Small wording change to syndicate collaborator greetings.
+
+
Fox McCloud updated:
+
+
Botany nerfed; will need ambrosia gaia earth's blood to make a tray self-sustaining
+
Gene machine now requires heavy upgrading to make use of transferring high quality genes from one plant to another
+
Starthistle can now be grown
+
Adds in red and regular onions; slice them for onion rings; cook them for even more delicious onion rings
+
+
Kyep updated:
+
+
Playing as a smite/bless hunter, or syndie infiltration team member, now requires that you be traitor-eligible. IE: have enough playtime, and the preference enabled.
+
+
Purpose2 updated:
+
+
BoxStation: Adds a garbage receptacle by the kitchen. Don't forget to bus your plates.
+
BoxStation: Fixes an inappropriate access restriction on one part of an airlock, and ensures the buttons are visible.
+
BoxStation: Changes the now erroneous Science Shuttle Console on the bridge to a Labor Camp Shuttle Console.
+
Adds screwdrivers to Medical by the cell chargers for recharging the defibs.
+
+
+
05 August 2017
+
Purpose2 updated:
+
+
Karma message will now point you in the right direction again.
+
+
+
03 August 2017
+
Fox McCloud updated:
+
+
Internal organs can take damage again, brain damage can be fixed again, and you now take the proper damage from external sources to limbs, IPCs surviving EMPs, and robo limbs never malfunctioning
+
+
+
02 August 2017
+
Fox McCloud updated:
+
+
removed a stasis book from the medical break room
+
+
+
31 July 2017
+
Birdtalon updated:
+
+
Protolathe stock part printing no longer takes a lifetime.
+
+
+
30 July 2017
+
FreeStylaLT updated:
+
+
Fixed erroneous pipes on z5
+
+
Kyep updated:
+
+
Evil-minded players can no longer use the Gateway's Mother of Terror spider to create an infestation on-station.
+
+
+
29 July 2017
+
Fox McCloud updated:
+
+
Dead hearts now induce a heart attack
+
Fixed concentrated initro never metabolizing
+
+
FreeStylaLT updated:
+
+
replaces generic Mining z-level with Meta's
+
+
Purpose2 updated:
+
+
MetaStation: Adds the missing kitchen windows
+
MetaStation: Nerfs the Top Hat equivalent of the Sword in the Stone.
+
MetaStation: Adds a Pet Supply vendor, chefs now make sushi again!
+
+
+
27 July 2017
+
Birdtalon updated:
+
+
Protolathe speed now increases when upgraded with manipulators.
+
+
+
26 July 2017
+
Citinited updated:
+
+
The autopsy drawer's description makes more sense.
+
+
+
25 July 2017
+
Birdtalon updated:
+
+
Reduces the volume of the electric guitars
+
+
FlattestGuitar updated:
+
+
Antagonists will no longer get the objective to steal slime extracts and plasma tanks.
+
The Captain has a swanky high-tech jetpack now. Antagonists will try to steal this one instead of *any* jetpack.
+
+
Fox McCloud updated:
+
+
You can now point while voluntarily lying down
+
shotgun darts and syringe darts no longer react their reagents on hit (they will still transfer reagents)
+
removes cryostasis bag
+
+
FreeStylaLT updated:
+
+
Removed sci outpost and dock from Metastation and Cyberiad
+
Added a Mining Outpost to the northernmost point of the Asteroid.
+
+
Kluys, Kyep & DarkLordpyro updated:
+
+
Emagged drones are now readily identifiable, as their lights turn red.
+
+
Kyep updated:
+
+
Eating as Ian (and other player-controlled corgis) is now rate-limited.
+
Reagents placed in shotgun shells will now react. It is no longer possible to make explosive shotgun darts by using regular darts like cryobeakers.
+
Admins' Smite command has been upgraded. No longer limited to Dark Priests, it can now send over a dozen different entities in search of its target, from the comic, like Greytiders, Tunnel Clowns, Masked Killers and Mime Assasins, to the serious, such as Syndicates, Soviets, Dark Lords and more. All come with a dust implant. These same characters can also be sent to protect specific crew members, so they aren't predictable.
+
The 'reaper' admin outfit now has a working briefcase.
+
Use of the 'Bless' command to bestow powers no longer causes genetic damage.
+
+
imsxz updated:
+
+
makes HONK rifle selfcharge
+
+
owenowen212 updated:
+
+
Adds the clownish language to honk squad members.
+
+
+
24 July 2017
+
FlattestGuitar updated:
+
+
Adds a taste system! Drink or eat stuff to find out what it tastes like!
+
+
Kyep updated:
+
+
it is no longer possible to use a sentience potion to convert space pirates in the beach away mission to your side. Nor is this possible with other sentient NPCs, such as syndies or russians.
+
+
+
23 July 2017
+
Fox McCloud updated:
+
+
Fixes cloners causing infections in clonees
+
+
+
22 July 2017
+
Crazylemon64 updated:
+
+
Slipping now outputs a visible message instead of a personal one
+
+
Fox McCloud updated:
+
+
Fixes IPCs and Diona being immune to weapon knockdown
+
+
Kyep updated:
+
+
Terror Spider away mission is now harder to cheese.
+
Loading a different character while in the lobby will now update the character name listed on the lobby screen. Same when you rename an existing character.
+
Blood decals are no longer movable. This means LINDA cannot move them, spiders cannot wrap them, etc.
+
+
+
21 July 2017
+
Purpose2 updated:
+
+
MetaStation: Adds a brand new Medbay!
+
MetaStation: Adds the dogbeds to the CMO/HoS office
+
MetaStation: Adds Sergeant Araneus back to the HoS's office. HoS beware.
+
MetaStation: Adds a processing area to the brig.
+
MetaStation: Adds the Gamma Armory.
+
MetaStation: Adds two additional brig cells
+
MetaStation: Adds a morgue slab to the Brig Phys office
+
MetaStation: Morgue has a swanky new office, directly connected to Cloning.
+
MetaStation: Robotics gets gloves and masks.
+
MetaStation: Adds shutters to R&D and Genetics.
+
MetaStation: Adds a Paramedic's office.
+
MetaStation: Adds a fully function containment grid.
+
MetaStation: Moves Monitor Encryption key to the RD's office again
+
MetaStation: Dorms have glass doors and fewer tinted windows
+
Metastation: Engine Containment now has Blast Doors instead of Shutters.
+
Metastation: Execution chamber blast doors are no longer see-through.
+
Metastation: Only the appropriate plastic flaps should be see-through.
+
MetaStation: Botany is no longer all-access
+
MetaStation: Science gets access to the Science outpost again... for now...
+
MetaStation: Fixes camera network monitors
+
MetaStation: Church shutters block vision again
+
MetaStation: Adds the missing Armory shutter button.
+
MetaStation: Removes tinted windows from R&D & Genetics
+
+
+
20 July 2017
+
Purpose2 updated:
+
+
Stops vampires spawning in the church.
+
+
+
19 July 2017
+
Fox McCloud updated:
+
+
Fixes dismembering and some damage transfers (when limb damage is maxed out) being inconsistent
+
can no longer dismember groins
+
Cleans up human examine code to be better laid out and more consistent; minor grammatical changes and some fixes; consistency should be retained for species that lack a pulse. Soul departure now properly checks for if the person can re-enter their corpse or not. Also resolves issues with FAKE DEATH examination.
+
Adds in gunshot blood splattering
+
+
+
18 July 2017
+
Fox McCloud updated:
+
+
Fixes blood volume being able to exceed 560
+
+
Purpose2 updated:
+
+
The Arrival's Trader Dock now cycles properly.
+
+
+
16 July 2017
+
Ataman updated:
+
+
Fixed diona nymphs needing oxygen and getting cold.
+
+
Crazylemon64 updated:
+
+
Cable laying by clicking the cable you want to join to works now
+
+
KasparoVy updated:
+
+
Fixes a bug with Vampire Shapeshift where you didn't get a name appropriate to your species and clarifies the ability description.
+
Fixes a bug with DNA scramblers whereby you wouldn't get a name appropriate to your species.
+
+
+
15 July 2017
+
Fox McCloud updated:
+
+
Fixes blood oddities with vampires
+
+
Kyep updated:
+
+
Mechs firing missiles no longer cause the missiles to drop at their feet, as if frozen in midair.
+
+
imsxz updated:
+
+
Edits the syndicate soft suit helmet's description to match the suit's.
+
+
+
13 July 2017
+
Fox McCloud updated:
+
+
Fixes blood volume and type not showing up properly on health analyzer
+
Fixes exotic blood names being incorrect
+
fix examining/checking yourself/others for bleeding/bandaging
+
Everything that involves bandaging now properly uses the new blood system
+
Fixes species exotic blood being injected into a mob not increasing their blood volume (slimes rejoice)
+
Fixed faked deaths still allowing for bleeding
+
Fixes IV drips not transferring over the proper amount of blood
+
Embedded objects will cause additional bleeding
+
Adds in heparin, a drug that can cause bleeding
+
medical stacks can be used multiple times on the same limb
+
Blood depletes in the body a lot faster now, due to blood refactor changes
some diseases now bypasse species virus immunity (kuru, TB, and appendicitis)
+
+
+
11 July 2017
+
Fethas and tigercat updated:
+
+
blood trails
+
blood is now eaiser to decrease/increase .
+
revamps about every method of adding blood to something, floors, walls, doors, PEOPLE.
+
+
+
10 July 2017
+
AffectedArc07 updated:
+
+
APC frames now have the correct texture
+
+
Birdtalon updated:
+
+
Pool contractors have been back to school and can now spell "safety" on the controller correctly.
+
Minor change to blob description to address grammar issue.
+
+
Citinited updated:
+
+
Superfart once again works ass intended.
+
+
Fox McCloud updated:
+
+
Radiation poisoning no longer permastuns, but deals burn damage now and has increased mutation chances
+
adds in electric guitars
+
can now craft violins and electric guitars
+
purchase electric guitars at the cargo store
+
service borgs now have an electric guitar, too
+
lowered the price of instruments, at cargo store, to 500
+
Fixed violins not having an in-hand icon
+
+
+
08 July 2017
+
Citinited updated:
+
+
Rainbow and mime crayons will now change colour as intended.
+
+
Fox McCloud updated:
+
+
Advanced mop slightly slower at cleaning and holds less reagents, but now regenerates water if turned on
+
Blood (on the floor) that has viruses in it will now properly infect you, if you get near
+
+
Kyep updated:
+
+
It is no longer possible to prioritize a job with no open slots, or close any job slots for a job that is already prioritized, as either of these actions could lead to a situation where a job is prioritized without people being able to join as it.
+
+
+
05 July 2017
+
Purpose2 updated:
+
+
Anomalies will once again drop cores.
+
+
+
04 July 2017
+
Birdtalon updated:
+
+
Traitor medical chemists can now access syndicate poison bottles.
+
+
Citinited updated:
+
+
AIs and cyborgs can now toggle liquid dispensers by ctrl-clicking them, and can make them dispense foam by alt-clicking.
+
+
Citinited & LightFire53 updated:
+
+
Adds the plasmaman coroner suit, the plasmaman geneticist suit, and the plasmaman virologist suit. Spooky purple skeletons everywhere rejoice!
+
+
Fethas updated:
+
+
Adds medical gowns to medical wardrobes.
+
+
Fox McCloud updated:
+
+
Syndicate bombs now have visible timers for observers
+
Syndicate bombs tick more often
+
Syndnicate bombs can be deconstructed into plasteel if it is fully defused and has no bomb core
+
Can make Cryo, Pyro, and time released chemical grenades at R&D
+
Can make syndicate chemical bombs utilizing crafting
+
love just got more powerful; it now prevents a mob from being on anything other than help intent
+
IPCs can now process the love reagent
+
Adds in radio jammers to the traitor uplink
+
Adds in breathing tube augment to R&D
+
Adds in arm toolset augment to R&D
+
IPC cell charging device is now inside their right arm, as opposed to chest
+
IPC cell charging device can now be produced in mech fabricators
+
+
Ionward updated:
+
+
Greys now have properly fitting sprites for most head clothing items!
+
+
Kyep updated:
+
+
Gimmick Teams are now more configurable.
+
+
Vivalas updated:
+
+
"Tweaks" SecHUDs to only display criminal status of people if their face is uncovered or they have no ID.
+
+
+
03 July 2017
+
Fethas updated:
+
+
fixes issue with hand teleporter not working in active hands
+
+
fludd12 updated:
+
+
Greys are now PROPERLY immune to sulfuric acid.
+
Greys don't pretend to touch their heads when they don't manage to anymore.
+
+
+
01 July 2017
+
Fox McCloud updated:
+
+
Re-enables object embedding system; embedding objects now cause more damage than before
+
Adds in throwing stars kit to the traitor uplink
+
bullets no longer leave shrapnel
+
+
+
30 June 2017
+
fludd12 updated:
+
+
Greys treat Sulfuric Acid as if it were water. They also treat water as if it were sulfuric acid.
+
Grey language is now Z-level wide, but requires you to be able to put a finger to your temple. (Requires at least one hand not disabled and not stunned.)
+
Remote Talk is buffed to have a range of two screens, and has some minor formatting changes!
+
Remote Talk no longer lets you magically know the true name of whoever you speak with.
+
+
+
29 June 2017
+
Fox McCloud updated:
+
+
Fixes limbs being an open wound after augmentation
+
+
Kluys updated:
+
+
Bob ross painting in the captains office called "calming painting".
+Also changes around the entertainment monitor and light switch to accomodate.
+
Clown painting was named "\improper mech painting"
+
+
+
28 June 2017
+
Fox McCloud updated:
+
+
Fix's IPC head customization
+
+
Purpose2 and Re-Opened by Fethas updated:
+
+
Rare Sentience event, the mice now want coffee!
+
+
+
27 June 2017
+
Alexshreds updated:
+
+
EMPs now disable radios for a period of time
+
+
Citinited updated:
+
+
Adds the Rapid Pipe Dispenser (RPD). All Atmospherics Technician lockers and the Chief Engineer's locker get one each.
+
+
Code Fethas and Sprites Phantasmicdream updated:
+
+
Fancy Victorian Clothes
+
+
FlattestGuitar updated:
+
+
defibs work even if you don't target the chest
+
Chaplain's soul stone is now opt-in.
+
+
Fox McCloud updated:
+
+
Can now augment all non-head limbs with surgery
+
Can select the company design of a limb by using a robot part in your hands
+
+
Kyep updated:
+
+
Gamma ship now looks like a real supply pod/ship, doesn't encourage wizards/vampires to hide in it, and has been updated with a wall-mounted charger and smarter layout.
+
Fixed a bug causing gamma armory mech recharger to be unusable after gamma alert was declared.
+
Admins may now spawn 'Gimmick' teams, including Janitorial ERT, Paranormal ERT, and more. Any admin outfit, any mission, spawned anywhere.
+
Paranormal ERT outfit now exists. It acts like a red security ERT, except with focus on fighting paranormal threats.
+
Janitorial ERT now gets ERT headset, not centcom headset. Also, they now get a survival box, and a flashlight.
+
New 'department' shuttle now has more public-access seating.
+
+
ProperPants updated:
+
+
Plasmaman virologists now spawn with a medical plasmasuit instead of an assistant one.
+
+
Purpose2 updated:
+
+
Water coolers have been fitted with better bolts, enabling them to be loosened and moved.
+
Antag barbers scissors now have the same name as regular scissors.
+
AIs door open link is now [O] rather than [OPEN].
+
The Syndicate once more recognises the Coroner as a member of the medical team for purposes for uplink items.
+
The chef may now tap into the Syndicate's poison networks for use in his dishes.
+
The chef's supply crate now comes with another rolling pin. Stop misplacing these.
+
+
tigercat2000 updated:
+
+
Karma returned to the Special Verbs tab
+
+
+
26 June 2017
+
Crazylemon64 updated:
+
+
TK can now manipulate adjacent tiles. Use throw mode to override this if you want to move an object a single tile.
+
TK can now remotely manipulate item stacks.
+
TK can now remotely operate an RCD
+
TK now behaves more consistently regarding interacting with various objects remotely
+
+
Kyep updated:
+
+
ID card consoles can now be used to prioritize any on-station job, including head jobs and karma jobs.
+
Playing as a drone now requires 10h of playtime.
+
Admin-ghosts can now interact with (ie: activate) the drone fab without having to spawn in as engineer to do so.
+
Prioritized jobs now lose their priority status once all their slots are filled. In the event someone with a formerly prioritized job cryos, the HoP may want to re-prioritize the job.
+
+
Purpose2 updated:
+
+
Coroners are more battlehardened, and thus don't throw up around dead bodies anymore.
+
+
+
25 June 2017
+
Kyep updated:
+
+
Trial admins no longer see a permissions error when opening player panel.
+
+
+
24 June 2017
+
Allfd updated:
+
+
Ported growl and howl sounds from Goon
+
Added growl and howl emotes to Vulpkanin
+
+
Kyep updated:
+
+
Activating a dust implant no longer causes NODROP items to drop.
+
+
Purpose2 updated:
+
+
The *slap emote now has a cooldown like all other noise making emotes.
+
+
SamHPurp updated:
+
+
The Coroner will respect the CMO's Authoritah.
+
+
+
23 June 2017
+
Kyep updated:
+
+
Smite/Bless commands are now restricted to Game Admins. (admins with R_EVENT)
+
Admins can now access telecomms while ghosted.
+
+
Vivalas updated:
+
+
Buckling mobs to beds now displays them correctly.
+
+
+
22 June 2017
+
Crazylemon64 updated:
+
+
Cloners now malfunction if the original comes back to life
+
+
Purpose2 updated:
+
+
RCDs can no longer construct multiple airlocks on a single tile
+
+
+
21 June 2017
+
tigercat2000 updated:
+
+
Changelings are now tentacle monsters. Give them a schoolgirl outfit.
+
+
+
20 June 2017
+
Purpose2 updated:
+
+
Fixes Fluorine's non-functionality in plants.
+
+
+
19 June 2017
+
Fox McCloud updated:
+
+
Diona nutrition bar should no longer flicker constantly
+
+
+
18 June 2017
+
Citinited updated:
+
+
Using a screwdriver on a camera console will now deconstruct it instead of opening the camera window.
+
+
+
16 June 2017
+
Alffd updated:
+
+
Makes kittens visible when resting
+
+
Fethas updated:
+
+
Public Wiggler Tail
+
Chaplains have some new clothes in thier locker.
+
+
Fox McCloud updated:
+
+
tweaked Revenant and slaughter demon movement speed
+
Spiderbots have been slowed down to human levels
+
Spiderbots melee attack consistently deals 2 damage, deals burn, and plays a sparks sound
+
Spiderbots no longer have a built in camera
+
Spiderbots now have 40 health (previously 10)
+
Attacking a spiderbot more consistent with other simple mobs
+
Healing a spiderbot with a welder now plays a sound and incurs a cooldown
+
Spiderbots can no longer carry items
+
Emagging a spiderbot makes it loyal to the person who emagged it. Additionally, it gains 20 extra health, its shocks will do 15 damage, and will explode on death
+
+
FreeStylaLT updated:
+
+
Changed Araneus' spawn location so he wouldn't break tables at round-start anymore
+
+
Kyep updated:
+
+
HoPs can now set jobs as 'priority'. Priority jobs are highlighted on the latejoin screen. This allows HoPs to proactively broadcast that they need more people to fill those jobs - and reduces the chance of critical crew shortages.
+
+
Purpose2 updated:
+
+
Soylen Viridians are now correctly Soylent Viridians. Nanotrasen will still not confirm rumours of the contents of these nor Soylent Greens however.
+
Nanotrasen is now more consistent with brand management.
+
An array of typos, grammatical tweaks and other pedantic fixes.
+
Adds a jobs board to the Newscaster. See what roles are available before seeing the HoP!
+
+
TullyBurnalot updated:
+
+
Autopsy Scanners will now print out Coroner Reports when a pen is used on them
+
+
alexkar598 updated:
+
+
Rename Spagetti to Spaghetti
+
+
+
13 June 2017
+
KasparoVy updated:
+
+
Moves a hidden emergency locker to where it is visible.
+
+
Vivalas updated:
+
+
Brig timers will now update the records of those who are imprisoned in their cell, as long as their name is entered correctly.
+
Sentences and arresting officers are announced over the security channel by brig timers, as well as the names of those who end timers manually.
+
+
+
10 June 2017
+
Alffd updated:
+
+
Ports Incoming5643's persistence features for Runtime from TG
+
Ports additional cat NPC emotes from TG
+
+
Citinited updated:
+
+
Disconnecting before the shuttle leaves after having spent karma will no longer prompt you to spend karma.
+
+
FalseIncarnate updated:
+
+
Adds Highlander Style, granted to the wielder of Highlander Claymores. This martial art allows you to deflect ranged attacks from the weapons of COWARDS. FOR THE HONOR OF THE HIGHLANDERS!
+
Highlander now equips combatants with a Highlander claymore instead of a normal claymore. FIGHT ON BROTHERS!
+
+
+
09 June 2017
+
Alexshreds updated:
+
+
Taking mhelps no longer gives mhelping players your IC name
+
+
FlattyPatty updated:
+
+
Added forensics gloves for the Detective.
+
+
Fox McCloud updated:
+
+
Paramedic door is no longer diamond
+
Fixes the backwards health analyzer sprite
+
Remove adrenaline and freedom implants from R&D
+
Added chem and tracking implants to R&D
+
+
KasparoVy updated:
+
+
Adds some sanity checking to the RCS.
+
The cargo shuttle no longer permits RCS telepads.
+
+
Kyep updated:
+
+
glowshrooms are now destroyable with two hits from a wirecutter.
+
New 'department' shuttle, which can be sent by CC instead of the regular evac shuttle.
+
The gods have grown tired of prayers requesting freebies, and developed some new curses with which to smite those who would treat them like miracle vending machines.
+
+
alexkar598 updated:
+
+
Surgury holosign switch has correct icon at roundstart
+
+
tigercat2000 updated:
+
+
You can now zoom in with the Set View Range option in your Preferences tab!
+
+
+
08 June 2017
+
Alexshreds updated:
+
+
Hyphema and Ocular Restoration are now possible to evolve from viruses
+
+
+
07 June 2017
+
Fethas updated:
+
+
adds cardboard cutouts..now you can trick the station into thinkings it shadowlings!
+
+
tigercat2000 updated:
+
+
Luxury versions of the bluespace shelter capsule! Currently not obtainable.
+
Black Carpet can now be crafted using a stack of carpet and a crayon.
+
Black fancy tables can now be crafted using Black Carpet.
+
Shower curtains can now be recoloured with crayons, unscrewed from the floor, disassembled with wire cutters, and reassembled using cloth, plastic, and a metal rod.
+
+
+
06 June 2017
+
DarkPyrolord updated:
+
+
Plasmamen should be able to become vampires on normal vampire rounds.
+
+
Fox McCloud updated:
+
+
adjust the mech tesla, immolator, and disabler techs to bring it in line with the tech refactor
+
+
Kyep updated:
+
+
Instagib lasers now work against non-carbon mobs, such as animals and borgs.
+
+
imsxz updated:
+
+
Sergeant Araneus now spawns at full HP.
+
+
+
04 June 2017
+
Crazylemon64 updated:
+
+
Clone's hearts now start operational
+
EMP'd clone pods can now be emptied again
+
+
FreeStylaLT updated:
+
+
Cell 6 is now connected to the atmos system properly.
+
+
+
03 June 2017
+
FlattestGuitar updated:
+
+
PACMAN boards and pico manipulators now have proper research levels
+
+
+
01 June 2017
+
Alexshreds updated:
+
+
Ian's hardsuit is no longer invisible
+
+
FreeStylaLT updated:
+
+
Gamma armory no longer affected by brig events.
+
Outer armory windoor access has been lowered to Security Officer+, instead of Warden+.
+
Removed a redundant door in the brig's main hallway.
+
Removed a redundant fire alarm, placed it elsewhere in the north hallway.
+
+
Kyep updated:
+
+
ERTs no longer start penniless, unable to afford even basic food, or coffee.
+
+
Purpose2 updated:
+
+
Adds a build-time on Tables & Racks.
+
+
tigercat2000 updated:
+
+
Upgrading the Exosuit Fabricator and Protolathe with the right parts will lower item costs
+
Added an item to Cargo that RnD can use
+
Tweaks the tech levels for many items and the required tech levels for their designs. This is to make RnD more of a station-wide effort.
+
RnD tech level skipping skips 1 level further
+
The Destructive Analyzer will only prompt the user if tech levels will not be increased.
+
The Experimentor can no longer raise tech levels of items. It can however discover the tech levels of strange objects.
+
Removes the Autolathe from the RnD Room.
+
Removed the Forensic Scanner from RnD. Cargo can order a Forensics crate now.
+
+
+
31 May 2017
+
FalseIncarnate updated:
+
+
Shrimp and electric eels properly lay their own eggs again if they have a suitable partner.
+
+
Xantholne updated:
+
+
Virologists actually spawn with their skirt
+
Coroner now can finally spawn with some Medical loadout clothes.
+
Medical Doctors will stop spawning with Chemist/Virologist Skirts
+
CMOs won't spawn with a virologist skirt anymore.
+
Virologists and Chemists wont spawn with a Medical Doctor skirt anymore.
+
+
+
30 May 2017
+
Fruerlund updated:
+
+
You can now take out pens by CTRL Clicking PDAs
+
+
+
29 May 2017
+
Jovaniph updated:
+
+
Two welding goggles on in the atmos room
+
+
Purpose2 updated:
+
+
Increases the size of Megaphones.
+
Headset encryption keys are now 'small' items.
+
+
Tayyyyyyy, FlattestGuitar updated:
+
+
A targeting mode-esque message and sound when you point at something with a gun in your active hand
+
+
+
28 May 2017
+
Fox McCloud updated:
+
+
Fixes various mobs moving around faster than intended
+
+
+
27 May 2017
+
Crazylemon64 updated:
+
+
Cloning now can be halted at any point, but ejecting too early may result in clones with missing body parts.
+
Slime people now no longer spontaneously die
+
+
+
26 May 2017
+
FlattyPatty updated:
+
+
Removes gateway hotel xeno embryo for the crew's safety.
+
+
+
25 May 2017
+
FalseIncarnate updated:
+
+
Matter Eater now requires your mouth be uncovered before you can eat matter.
+
+
Fethas updated:
+
+
PLASMAMAN ATMOS SUITS ARE NOW THE SAME AS REGULAR ATMOS SUITS FLAG WISE! AND SO IS THE CE SUIT
+
+
Kyep updated:
+
+
Fixed some mapping bugs on Centcom, e.g: shuttle medbay no longer has black walls.
+
+
Purpose2 updated:
+
+
Metastation - Adds the Paramedic's cart and locker.
+
Metastation - Adds a backup set of paramedic keys in the CMO's office.
+
Metastation - Engine no longer hotwired.
+
Metastation - Turbine doors now function properly.
+
Metastation - Toxin Mixing's Controller is now accessible.
+
Metastation - Moved Containment out a single tile, to fix irregularities with Singularity setups.
+
Metastation - Reduced redundant redundancies in the Atmos/Wiring.
+
Metastation - removed blob spawn that was only a few tiles from Cryostorage....
+
Drones can now grip Tracker Electronics & Vending Refills
+
+
Tayyyyyyy, PhantasmicDream updated:
+
+
Skrell can put a pocket sized item in their head tentacles, which can be dislodged via stunning, stripping, or death
+
Skrell can no longer have their tentacles shaved off
+
Minor grammar fix for putting stuff that's too big into containers
+
+
+
24 May 2017
+
Kyep updated:
+
+
Every head of staff now has a Department Management Console in their office. This is a very limited version of the ID console that they can use to demote people out of their departments, or move people between jobs in their department. These consoles cannot be used to hire anyone, or to accept cross-department transfers.
+
+
+
23 May 2017
+
Fethas updated:
+
+
Lockets and necklaces to the loadout. Lockets can hold paper and photos
+
Fethas fluff item
+
+
Purpose2 updated:
+
+
Adds functionality for the Atmos/Engineering Minimap to update to the right station.
+
+
+
22 May 2017
+
DarkPyrolord updated:
+
+
Rubber pellets should no longer embed.
+
Bananas fired from the staff of the honkmother should no longer embed, or be called bullets.
+
+
Kyep updated:
+
+
Adds mech-mounted variants of the existing tesla, immolator, and x-ray laser guns, with the same material and tech requirements. Admin-only Seraph mech also gets better weapons.
+
+
+
21 May 2017
+
KasparoVy updated:
+
+
Fixes a bug where only the fat roundstart disability could be selected.
+
+
+
20 May 2017
+
FlattestGuitar updated:
+
+
Adds a jobban-checking verb to the OOC tab.
+
+
KasparoVy updated:
+
+
You can now set your character's auto-accent at character creation. The verb still exists in the OOC tab.
+
+
Kyep updated:
+
+
Antag roles now have playtime requirements.
+
+
Kyep: updated:
+
+
Updated CC map.
+
+
Xantholne updated:
+
+
The Coroner now has an actual job icon.
+
+
+
19 May 2017
+
IK3I updated:
+
+
Empath stops telling you how much it hurts to not be human
+
+
MarsM0nd updated:
+
+
NanoUI map now shows the up-to-date map.
+
+
Purpose2 updated:
+
+
Coroner no longer alt title for MD
+
Adds Coroner job as its own job.
+
Adds a swanky new office for the Coroner.
+
+
+
18 May 2017
+
FreeStylaLT updated:
+
+
Added a Newscaster to Brig Toilet.
+
+
Purpose2 updated:
+
+
Adds a subtle chat-window reminder for karma on Shuttle departure. Disable/enable via preferences tab.
+
Removes the ugly round-end karma popup.
+
+
TullyBurnalot updated:
+
+
Deaf people cannot hear tape recordings anymore
+
+
+
17 May 2017
+
Fethas updated:
+
+
MORE GREY SPRITES!
+
+
FlattestGuitar updated:
+
+
You can now silence shoes just by using some duct tape on them! Shoe rags no longer exist.
+
+
Fox McCloud updated:
+
+
Neuro-toxin bar drink weakens after 13 cycles as opposed to instantly
+
+
Purpose2 updated:
+
+
Makes the new posters actually spawnable.
+
Fixes far more spelling errors than there ever should have been on the posters.
+
+
Travelling Merchant updated:
+
+
Adds a hiss emote for Unathi.
+
+
+
16 May 2017
+
FlattestGuitar updated:
+
+
Brig lockers now have radios and prisoner IDs. As per SOP!
+
+
FreeStylaLT updated:
+
+
Fixed broken disposals in brig.
+
Returned missing Sergeant Araneus to HoS office.
+
Fixed missing floor tiles in the execution hallway in Brig.
+
Remapped the entire Brig.
+
+
Kyep updated:
+
+
changed security officer job slots from 5 to 7.
+
+
uraniummeltdown updated:
+
+
You can now resist out of straightjackets
+
Straightjacketed people can be handcuffed
+
+
+
15 May 2017
+
TullyBurnalot updated:
+
+
Disposal Bin Light now works with thrown items
+
Fixes typos with cowboy items
+
+
+
13 May 2017
+
Fethas updated:
+
+
fixes a redundent add_cultist proc so cult memorize objectives works on new converts.
+
fixes an istype with IS_GAMEMODE_CULT
+
Narsie now will sometimes make a door a cult door..i thought i had that in the first time.
+
runed metal can now be only used on cult girders.
+
+
KasparoVy updated:
+
+
Fixes a sprite issue with the Unathi Dorsal Frill's webbing.
+
+
+
12 May 2017
+
Fethas updated:
+
+
Makes thrall examine use MASKCOVERMOUTH and HIDEFACE flags
+
fixes hudsunglass goof with vox.
+
+
Xantholne updated:
+
+
Changes name from dark brown to brown for the default cowboy boots
+
Gives a hint that the cowboy shirts are meant to be clipped on to your uniform
+
+
+
11 May 2017
+
Fethas updated:
+
+
Greybarber suit sprite.
+
Removes sec access from the paramedic
+
+
Fox McCloud updated:
+
+
can no longer make lethal medical patches with droppers
+
dripping reagents on someone with a dropper now incurs a 3 second delay like syringes
+
+
+
09 May 2017
+
Fethas updated:
+
+
a ton of grey clothing sprites.
+
+
+
08 May 2017
+
Purpose2 updated:
+
+
Adds a wire to the modular console on the bridge, fixing the Power Grid program.
+
+
uraniummeltdown updated:
+
+
Examine a reinforced wall for deconstruction and repair hints.
+
+
+
07 May 2017
+
GunDOSMk1 updated:
+
+
Adds Unathi cobra hood
+
+
Purpose2 updated:
+
+
Fixes the broken wiring re-electrifying the bridge window.
+
Adds the missing scrubber in Genetics holding pen
+
+
Twinmold updated:
+
+
No longer able to put grabs into kitchen equipment (deep-fried grab).
+
No longer able to put grabs inside of display cases.
+
+
+
06 May 2017
+
Allfd updated:
+
+
Thrown mobs will not step on broken glass while being thrown.
+
+
Fethas updated:
+
+
Fixes sacreficed your target not triggering the next objective.
+
YOU CAN NOW ONLY CONVERT HUMANS NOT MICE!
+
bloodspill tiles changed from base 100 (plus random number based on players) to 70.
+
Adds Tajaran veils as a loadout options
+
Racial loadout tab
+
+
LightFire69 updated:
+
+
Added a pretty plasmaman suit
+
+
uraniummeltdown updated:
+
+
Removed Robocop, Paladin, NT Default as roundstart lawsets.
+
+
+
05 May 2017
+
Fethas updated:
+
+
Magistrate, IAA, and BS will now spawn with the correct color dpet satchal and duffel
+
+
+
01 May 2017
+
Fethas updated:
+
+
There will now be an visual indicator to annouce that an incomming shuttle is about yo wreck you.
+
+
+
30 April 2017
+
scrubmcnoob updated:
+
+
Combat Shotguns now more expensive in cargo.
+
Shotgun ammo_boxes are now named and sprited as speedloaders that can speedload into a shotgun. Normal shotgun ammo boxes are just storage items for shells.
+
Adds in shotgun ammos readily available to be ordered from cargo in bulk and allows the ordering of Riot shotguns.
+
Adds in a Dragonsbreathe shotgun ammo box.
+
Tranq darts now have a sprite.
+
+
+
29 April 2017
+
FalseIncarnate updated:
+
+
Popcorn jellybeans require jellybeans to make.
+
Gum is no longer invisible, but is still very chewy.
+
+
Phantasmic Dream Art, Fethas PR updated:
+
+
Updates the shadowling sprite. Sprite by Dreamy
+
+
uraniummeltdown updated:
+
+
Examine a girder for (de)construction hints
+
Projectiles have a chance to pass through some girders
+
You can construct rough iron (false) walls with rods, wood (false) walls with wooden planks on a girder
+
Screwdriver a displaced girder to deconstruct it
+
Increased displaced girder health, decreased reinforced and cult girder health
+
False wall construction is no longer instant
+
Girder (de)construction messages should read better
+
+
+
28 April 2017
+
Alffd updated:
+
+
Adds Paperwork the sloth to cargo.
+
+
+
27 April 2017
+
Kyep updated:
+
+
Changed "suggested client version" from 510 to 511.
+
+
+
26 April 2017
+
FalseIncarnate updated:
+
+
Glowshrooms (and their subtypes) can be mass-cleared by scythes just like vines.
+
+
pinatacolada updated:
+
+
dirty surgery environments get you nasty infections
+
ghetto surgery internal organ disinfection with alcohol
+
dead limb revival surgery step
+
+
+
25 April 2017
+
Flattest updated:
+
+
Animated progress bars!
+
+
uraniummeltdown updated:
+
+
Runed girders have a clearer and bigger icon
+
Girder subtypes are properly named, "reinforced girder" and not "reinforced"
+
Summoned cult walls do not drop a girder or runed metal to prevent runed metal farming
+
Cult walls no longer have blood or human remains in them
+
Harvesters can smash more things and can summon cult walls and floors
+
Fixed not being able to make a cult wall with runed metal + runed girder
+
Runed girders will need to be deconstructed with a welder (or plasma cutter or jackhammer) instead of a wrench. Cultists can hit them with their tomes to instantly demolish them.
+
+
+
24 April 2017
+
Flattest updated:
+
+
Sleepers spit out their victims when deconstructed now.
+
+
+
23 April 2017
+
Citinited updated:
+
+
You can now fully insulate reinforced floors using a sheet of plasteel.
+
Certain floors in the turbine, incinerator, and toxins are now thermally insulated.
+
+
Crazylemon64 updated:
+
+
Reverts Norgad's east maintenance overhaul
+
+
IK3I updated:
+
+
flipping aliums now have a cooldown
+
Aliums have some more sounds to play with
+
+
Tayyyyyyy updated:
+
+
You can no longer use space pod verbs when restrained, dead, or otherwise incapacitated.
+
+
+
21 April 2017
+
Anticept updated:
+
+
Alternate Job Preference now defaults to "Return to Lobby if Preferences Unavailable". Only affects new players.
+
+
Fox McCloud updated:
+
+
Tesla can now damage blobs
+
Tesla causes machinery to overload and explode when zapping it
+
Tesla dissipates energy more slowly and is easier to charge up (making it more deadly when released)
+
Tesla will now dust mobs it bumps into
+
Tesla coils now have wires that can be pulsed to generate a tesla zap
+
+
Lady-Luck updated:
+
+
Makes several balance adjustments to existing syndicate bundles, generally making them more worthwhile.
+
Adds an Allies Cocktail object for the Bond bundle.
+
Adds the 'gadgets' syndicate bundle.
+
Removes the 'lordsingulo' and 'murder' syndicate bundles.
+
+
Spacemanspark updated:
+
+
Permits hoodies to carry flashlights.
+
+
Twinmold93 updated:
+
+
Adds attack options for deep fryers, grills, and ovens. Those breaking into the kitchen beware.
+
+
alexkar598 updated:
+
+
you can now click on things underwater
+
+
monster860 updated:
+
+
Adds an in-game way of viewing poll results
+
The player poll window automatically pops up if there is an active poll you haven't voted on.
+
Adds an browser popup for creating new polls
+
Your account needs to be at least 30 days old in order to vote on polls
+
+
+
19 April 2017
+
IK3I updated:
+
+
Chaplain now spawns with his bible
+
+
Xantholne updated:
+
+
You now correctly spawn with the CMO Skirt if selected in loadout menu
+
+
+
17 April 2017
+
KasparoVy updated:
+
+
The God-emperor of Mankind diskette's UI works again.
+
DNA UI injectors will now immediately update a person's eye colour.
+
+
Krausus updated:
+
+
You can no longer squeeze non-match objects into matchboxes.
+
+
+
16 April 2017
+
FalseIncarnate updated:
+
+
Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially.
+
Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor.
+
+
KasparoVy updated:
+
+
Adds secondary (facial) hair colours to the genome (UI). There are 6 new blocks.
+
Characters with secondary (facial) hair colours won't find they've turned black after cloning anymore.
+
+
Kyep updated:
+
+
Plasma dust no longer creates plasma gas on objects or turfs during reactions.
+
+
Twinmold93 updated:
+
+
Missing sprite for pod pilot Drask now added.
+
+
Xantholne updated:
+
+
Adds Medical Beret available via loadout menu
+
+
ZomgPonies updated:
+
+
Fixes Superhero ID cards
+
Fixes Griffin missing his Freedom Implant
+
Fixes ElectroNegmatic's Ability not working at all.
+
Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with the amount of people affected depending on how long you hold the power in for.
+
+
uraniummeltdown updated:
+
+
You can now create heat-proof glass airlocks by using a sheet of reinforced glass on the assembly during construction. Regular glass airlocks just require a sheet of glass.
+
+
+
11 April 2017
+
FalseIncarnate updated:
+
+
Damage done to the shuttle engines by a shadowling's "Extend Shuttle" ability now prevent the shuttle from being recalled to CentComm.
+
+
+
09 April 2017
+
Fox McCloud updated:
+
+
abductor glands now act as actual hearts; removing them induces heart failure
+
plasma gland no longer gibs you, but makes you vomit plasma instead
+
bodysnatcher gland no longer gibs you, but will deal brute damage instead
+
bloody gland will now drain blood instead of dealing brute damage
+
species change gland will now change your species until the gland is removed
+
adjusted the origin tech on a few gland
+
heart attacks will once again paralyse you and do slightly more brute damage
+
body snatch clones look more like their originator
+
Abductors can no longer use guns (minus their own alien energy gun)
+
Sending someone with an abductor teleport via the console will stun them for 3 cycles (doesn't apply with the advanced camera console)
+
Abductors can now purchase additional abductor vests
+
Abductors can lock/unlock vests
+
Purchasing supplies from the abductor console will no longer increase the amount of experiments you must do
+
Wonderprods will not induce sleep in those who are stunned OR sleeping
+
altered the origin tech of abductor tools
+
Can make abductor surgery tables from regular tables by adding silver sheets to an abductor table frame
+
Added a bunch more abductee objectives
+
abductors no long scream like girls
+
High capacity cells have 10,000 charge instead of 15,000
+
Mech equipment power costs minorly adjusted
+
APCs charge a bit faster
+
EMPs less effective against pods and mechs
+
Fixes not being able to recharge modular laptops/tablets
+
+
Purpose2 updated:
+
+
Welders must now been fueled and active to cut lattices.
+
+
+
06 April 2017
+
Fox McCloud updated:
+
+
Fixes autopsy report printing; print reports by clicking the device itself
+
+
davipatury updated:
+
+
Rapid Cable Layer now have an autolathe design.
+
+
+
05 April 2017
+
KasparoVy updated:
+
+
Adds a Tajaran facial hair style.
+
Adds a few new frill styles for Unathi.
+
Adds some new horn styles for Unathi.
+
Adds a couple new facial hair styles for Vulpkanin.
+
Adds a few new hair styles for Vulpkanin.
+
Updates Vulpkanin Adhara & Kajam hairstyles.
+
+
Purpose2 updated:
+
+
Can now take photos of the Blueprints to count as a completed objective.
+
Cryostorage console now stores the Null Rod & all variations.
+
Mime mech is now 'Reticence' as it should be
+
Fixes missing cult's Berserker Robe sprite.
+
Cryostorage console no longer stores hundreds of bomber jackets, and now stores hardsuits
+
Cryostorage console now catches and stores most unique objective items.
+
Corrects some typos and grammar.
+
You can now light cigarettes with Wands of Fireball, at the cost of your eyebrows.
+
+
Twinmold93 updated:
+
+
Buying poison pen will actually give you the poison pen now.
+
+
+
04 April 2017
+
FalseIncarnate updated:
+
+
Adds FullofSkittles's custom pAI sprites. Thanks FoS!
+
Custom sprites for cyborgs, AI, AI holograms, and pAI units no longer are restricted to a single name. Get your money's worth by using that borg sprite regardless of your version number!
+
+
+
03 April 2017
+
Kyep updated:
+
+
Ghosts manifested by cultists are no longer invincible, and an exploit allowing them to be made permanent has been fixed.
+
+
+
02 April 2017
+
KasparoVy updated:
+
+
Nuclear Operatives/ERT Members/Abductors will no longer spawn in with genetic quirks.
+
Thrown objects that cross a tile with non-full windows will no longer hit the window even if it isn't visually obstructing the path.
+
Shooting guns (i.e. tasers) in the above circumstances means that the taser shots won't be blocked by windows that aren't visually obstructing the path.
+
+
Kyep updated:
+
+
Adjusted Black Market Packers away mission. It now has some danger to it (carp), some more interesting stuff to find (syndi lab) and a challenge (fix the ship powergrid).
+
Slight adjustment to word lists based on our rules.
+
Removed thunderdome armor from centcom away mission.
+
Cultists now get a new sacrifice target when the current one cryos.
+
+
+
31 March 2017
+
Krausus updated:
+
+
Blobs are no longer nearly guaranteed to immediately tear themselves apart upon spawning.
+
+
Kyep updated:
+
+
Access to jobs is now based solely on Playtime, NOT days since BYOND account was registered.
+
+
+
30 March 2017
+
Crazylemon64 updated:
+
+
Cult shifter should work now
+
+
FlattestGuitar updated:
+
+
Strange Reagent only deals clone damage on a successful revival.
+
+
Fox McCloud updated:
+
+
Non-designated drinks now mix their colors from the reagents within them
+
Autopsies can now be performed without needing to cut someone open
+
Adds modular receiver to the maintenance loot system
+
Receivers can now be produced in hacked autolathes; no longer available in R&D protolathes.
+
removes the random "scary" sounds that play when walking about
+
+
KasparoVy updated:
+
+
You can now slam drinks/bottles/flasks by click-dragging them onto yourself while it's in your active hand.
+
+
Kyep updated:
+
+
The moonoutpost19 away mission should now be finishable, and more enjoyable to attempt.
+
+
uraniummeltdown updated:
+
+
Emagging a closed firelock does not permanently break it anymore, only opens it.
+
Emagged windoors should be able to be screwdriver+crowbar'd again.
+
Powered grilles now have a chance to zap you when you throw an object at them.
+
+
+
29 March 2017
+
Purpose2 updated:
+
+
'Roundstart malfunctioning' cameras now appropriately have their wires cut.
+
AI core camera can no longer be a 'roundstart malfunctioning' camera on both Box & Meta Stations.
+
+
+
28 March 2017
+
KasparoVy updated:
+
+
Skrell can now choose undergarments (undershirts, underpants, socks) at character creation and dressers.
+
Vox are now 20% less resilient to brute damage due to their light, porous and flexible skeletons.
+
+
uraniummeltdown updated:
+
+
Quick-replacing non-wooden tiles will only work with a crowbar in inactive hand instead of any item
+
+
+
27 March 2017
+
Crazylemon64 updated:
+
+
Away mission power works now.
+
+
Fox McCloud updated:
+
+
Fixes some stacks not wanting to stack with similar stacks (such as space cash)
+
+
KasparoVy updated:
+
+
Skrell have been greyscaled and darkened. You can now colour your Skrell characters as you please.
+
Kidan can now select from multiple different antennae head-accessory styles.
+
Kidan male/female bodies now have differences, namely mandible/torso structure.
+
Skrell flesh is now blue (like their blood), though you'll only ever see this under certain circumstances if they're dismembered.
+
+
Kyep updated:
+
+
The invisible floors in the engineering area of the UO45 away mission are no longer invisible. Previously, you had to crowbar up a seemingly invisible floor to make a wire appear.
+
Fixed several Terror Spider bugs. Including the notorious 'spiders can get stuck in vents' bug, the 'spiders ignore mechs' bug, and the 'prince is cheesable' bug.
+
Adjusted White & Empress spider abilities - webs spun by white spiders are now infectious.
+
+
Purpose2 updated:
+
+
Adds the Psychiatrist's bed/sofa for 5 metal.
+
Wooden chairs broken by animals no longer drop metal.
+
Abductors no longer have Syndicate ties.
+
Fixes material loss on some chair/bed/stool deconstruction types.
+
IPCs can no longer be DNA Scrambled.
+
Health analysers clunk again when upgraded
+
Resolves further grammatical/typo issues.
+
+
+
26 March 2017
+
FalseIncarnate updated:
+
+
Re-adds the telescopic scythe, the pinnacle of covert reaping technologies. Currently admin-spawn only, for use in the most dire of harvest times.
+
Scythes (normal and telescopic) should once again clear swathes through all but the hardiest of vines when in proper reaping configurations, and heavily damage those they don't outright destroy.
+
Ankle-high piles of dirt will no longer prevent you from stepping over them.
+
+
KasparoVy updated:
+
+
You can no longer climb through interdimensional rifts into cryopods.
+
Revenants can see properly in the dark again.
+
+
Kyep updated:
+
+
Adjusted Beach awaymission so it now includes deadly (but rewarding) pirate area.
+
Adjusted the centcom away mission to make it viable.
+
Deleted 'listening post' away mission.
+
+
Purpose2 updated:
+
+
QoL: Newly built APCs come unlocked.
+
QoL: Chief Engineer's locker has more building permits.
+
Assorted grammatical fixes.
+
+
Ty-Omaha updated:
+
+
Splints will display the proper sentence when applying them
+
+
uraniummeltdown updated:
+
+
Metastation: Fixed Gateway airlock access and Command Hallway vendor areas, virology smartfridge is correctly stocked, mass drivers now have tiny fans, Sec spacepod keys work on the Sec pod, Airlocks should have the correct icon, Firelocks/Windoors/Shutters should be layered correctly, Shutters should be facing the right direction
+
Drone fabricator consoles search for a fabricator in the same area instead of 3x3 range.
+
+
+
25 March 2017
+
Crazylemon64 updated:
+
+
All pens are now certified crayon-wax free!
+
+
Kyep updated:
+
+
Pipes in the Wizard Academy have been banished back under the carpet, where they belong.
+
+
+
24 March 2017
+
KasparoVy updated:
+
+
Red wire-cutters and red crowbars now appear correctly in-hands again. imgadd: The medical wrench and all the brass tools (screwdriver, crowbar, wrench, wire-cutters, welder) now have in-hand sprites of their own.
+
Adds TG's inhand icons for screwdrivers, crowbars, wrenches, wire-cutters and welders.
+
Slime People can wear underwear, undershirts and socks.
+
+
uraniummeltdown updated:
+
+
IV Drips are no longer dense objects, you can walk over them.
+
You can change gold and silver tiles into fancy versions by using them in hand.
+
+
+
23 March 2017
+
FalseIncarnate updated:
+
+
Fish breeding has been tweaked to support fish refusing to cross-breed and improved egg chances with same-species parents.
+
+
Fox McCloud updated:
+
+
Floors are now fully properly cleaned with mops and soap
+
Adds in emergency welding tool, fork, trays, drinking glasses, shot glasses, shakers, butcher cleavers, and riot darts to the autolathe
+
Adds all basic stock parts to the autolathe
+
re-arranges the autolathe menu to be more logical
+
light bulbs no longer require metal to produce
+
Incision management system can now cauterize
+
+
KasparoVy updated:
+
+
Unathi Security, Medical, Engineering and Syndicate side-facing hardsuit sprites have undergone weight reduction.
+
+
Kyep updated:
+
+
Chaplain's armor is no longer riot-grade. In addition, their nullrods do less damage.
+
+
MarsM0nd updated:
+
+
Conveyor switches can now set to left-only direction toggling.
+
+
Norgad updated:
+
+
Maintenance areas near arrivals, science, and the bar have been revamped.
+
+
uraniummeltdown updated:
+
+
Station lighting has less lighting power, this is not noticeable apart from maint and 1 bulb rooms being a bit darker.
+
Tweaked the potency scaling for glowshroom/glowberry light; high-potency plants no longer light up a huge area, but are slightly brighter.
+
Added Shadowshrooms as a glowshroom mutation. They do exactly what you'd expect.
+
+
+
22 March 2017
+
Crazylemon64 updated:
+
+
Rod form is now at half speed, and has a warning sound.
+
+
FlattestGuitar updated:
+
+
When a person's limb is dying, it will no longer notify the whole server of the ordeal
+
Welding tools no longer tell you about their span classes
+
+
KasparoVy updated:
+
+
Deconstructing beds now yields the same amount of metal as was used to make the bed.
+
The PA console will no longer appear as though it is fully constructed at the start of the round.
+
Ore Redemption Machines no longer eat IDs when deconstructed.
+
Ore Redemption Machines and Mining Equipment Vendors now spit out whatever IDs were in them when they lose power.
+
+
Krausus updated:
+
+
Personal crafting is now usable again for those with an Internet Explorer version below 11.
+
+
+
21 March 2017
+
Crazylemon64 updated:
+
+
Strange reagent now has a volume floor requirement to activate, induces clone damage, and may cause further trouble...
+
+
KasparoVy updated:
+
+
No-one escapes nuclear hellfire.
+
Secure fridges/freezers are now lead-lined and have thus become nuke resistant.
+
+
uraniummeltdown updated:
+
+
Baseball bats added to the game, are craftable from 5 wood planks.
+
Baseball burgers can be made with a baseball bat and a bun, either microwaved or table-crafted.
Fixes the exploit to produce infinite cable coil from airlocks.
+
+
Tayyyyyyy updated:
+
+
Added GPS devices to pod pilot and mechanic's offices
+
+
+
19 March 2017
+
Jovaniph updated:
+
+
Voxes can now wear soft caps.
+
+
Krausus updated:
+
+
Pest spray bottles are no longer invisible.
+
+
Kyep updated:
+
+
Wood doors in wild west map no longer constantly open/close
+
+
uraniummeltdown updated:
+
+
Shipping errors can sometimes cause the supply shuttle to receive an extra crate when ordering supplies.
+
Added dog beds! Can be made with 10 wood planks and deconstructed with a wrench. Ian's Bed added to Cyberiad and Metastation.
+
+
+
18 March 2017
+
Fox McCloud updated:
+
+
Fixes abductor surgeries
+
+
Jovaniph updated:
+
+
Unathi EVA suits
+
+
uraniummeltdown updated:
+
+
Shades now have directional sprites.
+
Attacking with glass shards now hurts your hand if not wearing gloves. Does not affect robotic hands though.
+
+
+
16 March 2017
+
FlattestGeetar updated:
+
+
Workboots are now in the loadout system.
+
Ports winter boots from /tg/
+
+
Jovaniph updated:
+
+
New sounds to Firelocks and Airlock External
+
Door closing sound to Airlocks - from yogstation
+
+
Markolie updated:
+
+
Fixed revenant night vision not working.
+
Fixed the "X attacked Y" message showing up when welding vents.
+
Fixed the follow button on the cell door timer radio message not working.
+
Fixed the Jaws of Life being unable to force unpowered doors.
+
Fixed a number of preference options being unavailable when modifying preferences while observing.
+
Fixed an issue where deleting security records wouldn't clear that player's wanted status properly.
+
Fixed the cult "first meal" sacrifice objective not counting properly. Also clarified what this objective actually entailed.
+
Fixed IPC's ocassionally being selected as a changeling "escape with X identity" target.
+
The character records and disabilities menus in the preferences menu no longer uses the plain white background, but uses the better looking blue layout instead.
+
+
+
15 March 2017
+
uraniummeltdown updated:
+
+
Plastic flaps can be deconstructed with tools and constructed using 5 sheets of plastic.
+
You can now damage grilles by throwing things at them.
+
You can rebuild broken grilles by using a metal rod on them.
+
Metal rods maximum amount reduced from 60 to 50.
+
+
+
14 March 2017
+
uraniummeltdown updated:
+
+
Strong supply talismans can now summon 5 sheets of runed metal.
+
+
+
13 March 2017
+
Kyep updated:
+
+
Syndicate mobs in the Wild West are no longer so stupid that they trip over, and die to, their own mines. This also means that they won't set their own buildings on fire anymore.
+
Phazons' phase ability now works again.
+
Phazons' toxin injector melee damage type (a weak melee attack) now works again.
+
+
uraniummeltdown updated:
+
+
Clicking on a tile with another tile and a crowbar or screwdriver in hand directly replaces the tile.
+
+
+
12 March 2017
+
Crazylemon64 updated:
+
+
Kudzu should now be less of (but still) a station-destroying force of nature.
+
Bluespace kudzu now only pierces a single layer of walls before losing its "charge".
+
Aggressive spread now does not bust rwalls, but does attack obstructing objects in its path.
+
Kudzu now only spreads on space turfs when it has specific mutations to do so.
+
Kudzu events should be more interesting on their own.
+
+
Jovaniph updated:
+
+
Adds Vulpkanin EVA suit sprite
+
+
Kyep updated:
+
+
Adjusted Wizard Academy to make it both more lethal, and more rewarding.
+
+
Markolie updated:
+
+
The system for picking ghosts to inhabit cultist slaughter demons now shows a confirmation prompt like most other role checks.
+
Fixed an issue where you could join as a cultist slaughter demon despite having antagHUD enabled.
+
Fixed an issue where it was possible to weld statues without any fuel.
+
It is no longer possible to spam the firelock force message.
+
+
Twinmold93 updated:
+
+
Employment record laptop to Head of Personnel's Office. Moves package wrap that was there to meeting room to be paired with the hand labeler there.
+
+
+
11 March 2017
+
Developed by XDTM, ported by davipatury updated:
+
+
Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
+
Added some new hallucinations.
+
Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
+
+
Flatty Patty updated:
+
+
all the tools have icons again
+
+
FlattyPatty updated:
+
+
Improved Nanotrasen click manufacturing procedures now allow the flashlights to make that classic clicking sound you know and love.
+
+
Fox McCloud updated:
+
+
Buckshot now does a max of 70 damage, down from 90
+
+
KasparoVy updated:
+
+
Fixes a bug with certain tail markings rendering when they shouldn't.
+
+
Markolie updated:
+
+
Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose if there's still an atmospherics alarm present.
+
Regular (non-heavy) firelocks will now properly respond to explosions (100% chance of being destroyed at severity 1 explosions and 50% at severity 2). Heavy firelocks are still only destroyed in severity 1 explosions.
+
Added a visible message to forcing airlocks with the Jaws of Life.
+
+
davipatury updated:
+
+
Ported Modular Computers from /tg/.
+
Ported Rapid Cable Layer from /vg/.
+
+
uraniummeltdown updated:
+
+
EVA has 2 more EVA Suits
+
Removed Vox-only EVA suits (the grey ones in EVA)
+
Vox can now wear EVA suits
+
+
+
10 March 2017
+
Jovaniph updated:
+
+
Recitence no longer makes a sound when turning
+
+
Markolie updated:
+
+
The DNA Vault station goal will now be marked as completed properly.
+
Multi-tile airlocks will now change their direction properly.
+
The atmos skirt loadout item will now be equipped properly on round start.
+
Fixes the inhand disabler sprite pointing the wrong way in some directions.
+
The Janicart will no longer act as a jetpack.
+
You can now resist out of a borer's control again.
+
Fixes the general antag ban not working on certain conversion antagonists.
+
Fixes removing the trunk from underneath a chute/bin causing all sorts of issues.
+
Fixes alt titles not showing up on ID's.
+
Mineral doors no longer block atmos (like they're supposed to).
+
Fixes the cortical borer hivemind talk not working.
+
Fixes detomatix cartridges not working *from* PDA's with an uplink (it now no longer *on* a PDA with an uplink to prevent blowing up fellow traitors).
+
Fixes NODROP interaction with secure closets.
+
Fixes some stray fruit at the Syndicate base on Z2.
+
Fixes an incorrect camera network in the courtroom.
+
Fixes an issue where AI's would go blind upon travelling into space.
+
The cortical borer hivemind talk key is now "bo".
+
Attempting to blow up an undetonatable PDA (such as the captain's) will now show a warning message. It will also no longer use up a charge.
+
Animals can now open mineral doors and mineral doors will no longer be closable if there's a mob inside.
+
Matter grippers can now carry firelock electronics as well as bluespace crystals (for construction).
+
Removes the pipe fitting on the table from atmospherics as it was broken.
+
+
+
09 March 2017
+
Crazylemon64 updated:
+
+
Adds an "ethereal beacon", an admin-only structure usable to attract ghosts to an area.
+
Adds several transformer machines to streamline the ghost-to-PC process.
+
+
LordJike updated:
+
+
Space Fries are now made by deep-frying potato wedges instead of processing them.
+
Introducing carrots inside the food processor gives you carrot wedges now.
+
Now you can make carrot fries by deep-frying carrot wedges instead of formerly processing the whole carrots.
+
+
Markolie updated:
+
+
Tools now have a "usesound" and "toolspeed" variable which allows different tool (levels) to have different sounds and speeds.
+
Robots spawn with tools that are twice as fast as regular tools.
+
Abductor agents now spawn with a toolbelt with specialized abductor tools that are very fast.
+
Abductor surgery tools are now much faster.
+
Abductor (surgery) tools can now be constructed in R&D with a sufficiently high "abductor" research level.
+
The abductor multitool will now display what each wire does.
+
Admin ghosts can now interact with wires and see what each wire does.
+
Adds a set of unique tools for the Chief Engineer that he is given in a unique toolbelt at roundstart. These tools are faster and can be created in R&D with a sufficiently high R&D level.
+
The AI detector has been refactored to have much more robust AI tracking.
+
+
+
08 March 2017
+
Alffd updated:
+
+
Farting on a bible now puts you at the mercy of the gods.
+
Removed automatic biblefarting gibbing.
+
+
FlaaaaaattestGuitar updated:
+
+
Magistrate now starts their shift with a pair of white gloves as well as Bridge and Meeting Room access.
+
+
Fox McCloud updated:
+
+
money is now far easier to use, and distribute in amounts you would like
+
+
Kyep updated:
+
+
Changed event probabilities, aiming for a more fun late game. In general, events that do very little (e.g: meaty ores, rogue drones) are less likely. Events that will keep people on their toes (e.g: anomalies) are more likely. Events that might cause people to observe rather than joining the round (e.g: Xenos) are less likely.
+
+
uraniummeltdown updated:
+
+
Wizard Hardsuit helmet and suit now have inhand sprites
+
+
+
07 March 2017
+
Crazylemon64 updated:
+
+
IPCs now come with a power cord implant to use to recharge from APCs.
+
IPCs can now be genderless.
+
+
Kyep updated:
+
+
Deleted 'challenge' away mission.
+
+
MarsM0nd updated:
+
+
Cultists get shoes on usage of the armor talisman.
+
Cultists only get equipment if they have the slot for it free, weapons are always spawned.
+
The tome does a more fitting description of the talisman of armor.
+
+
+
05 March 2017
+
Kyep updated:
+
+
Added Poison Pen, a stealthy way of applying a contact-based poison to paper. Available to Syndicate HoPs, QMs, and Cargo Techs.
+
Antags whose objectives are manually announced by an admin, or altered automatically as a result of their target cryoing, will now hear a warning sound. The sound is the same as the 'crew transfer vote called' sound. Additionally, the text notice for changed objectives is more obvious.
+
+
MarsM0nd updated:
+
+
The grey satchel uses now the correct sprite instead of the leather one.
+
+
+
04 March 2017
+
Markolie updated:
+
+
Ghosts can now interact with ore dispensers, mining equipment vendors and laptop vendors.
+
Admins can now interact with crates, closets, false walls and conveyor switches if they have advanced interaction enabled.
+
+
davipatury updated:
+
+
Newscaster now uses Nano-UI.
+
Tank dispenser now uses Nano-UI.
+
Passive gate, pump and volume pump now uses Nano-UI.
+
Atmospherics filter and mixer now uses Nano-UI.
+
Wires now uses Nano-UI.
+
+
+
03 March 2017
+
FlauntestGuitar updated:
+
+
You will now be prompted on a karma purchase to confirm that you clicked what you wanted to click
+
+
uraniummeltdown updated:
+
+
You can now change the input/output directons for Ore Redemption Machines by using a multitool on them with the panel open.
+
Bluespace RPED beams have a new sprite
+
+
+
01 March 2017
+
Crazylemon64 updated:
+
+
Kudzu vines now can yield materials if carefully tended to
+
+
Fethas updated:
+
+
2 second cooldown on the rest verb. You are not Neo, knock it off.
+
StopResting and StartResting Procs are not on the rest verb.
+
Various metastation fixes.
+
+
KasparoVy updated:
+
+
Plasmaman multiverse sword copies are now properly equipped (suit, helmet, internals, etc.)
+
Vox multiverse sword copies are now peoperly equipped (internals).
+
+
Kyep updated:
+
+
Fixed several Terror Spider things that should not be possible, like recharging wireless guns, the 'evil-looking spiderlings' instant meta, and spiderlings spacing themselves.
+
Several Terror Spider balance and fun tweaks, such as giving the Prince of Terror a new webbing ability, and ensuring queens/mothers can break open vents, so they cannot be completely shut out late-round.
+
+
Purpose2 updated:
+
+
Enables Cargo to order Wood planks
+
+
+
28 February 2017
+
KasparoVy updated:
+
+
Plasmaman suits will now only auto-extinguish if you're actually on fire (and not just taking a shower).
+
+
+
27 February 2017
+
uraniummeltdown updated:
+
+
Mineral statues are here! Use 5 sheets of any mineral including sandstone to make one. Be careful around plasma and uranium statues!
+
The mime's office now comes with a statue too.
+
Updated plasma, uranium and diamond floor sprites to TG's newer ones.
+
+
+
26 February 2017
+
Crazylemon64 updated:
+
+
Immovable rod events now vanish after going through the station once
+
Firelocks can now be operated by AIs again
+
Barbers and captains get the right stuff now
+
It's now possible to have random floors or walls when mapping
+
+
KasparoVy updated:
+
+
Fixes a bug where you could get a part of a rigsuit stuck to your hand by deploying it twice.
+
Improves the readability of some rigsuit verbs.
+
+
Kyep updated:
+
+
players will no longer spawn with loadout items their job has no access to.
+
AI & Borg upload consoles now have to be on the station zlevel to work.
+
+
davipatury updated:
+
+
ATM now uses Nano-UI.
+
+
+
25 February 2017
+
Crazylemon64 updated:
+
+
Telecomms monitor is now infused with fastitude
+
+
FlattestGuitar updated:
+
+
Escape has been re-bushed.
+
+
KasparoVy updated:
+
+
Reagent plasma has a weak healing effect on Plasmamen when injected and will not poison them.
+
Reagent oxygen is as toxic to Vox as reagent plasma is to just about anyone.
+
Plasmamen now join the shift with 2 suit auto-extinguisher refill cartridges which, individually, will fully refill an empty Plasmaman suit's autoextinguisherl.
+
Plasmaman suits now auto-extinguish and will be able to do so 5 times before they can be refilled by a cartridge.
+
Plasmamen no longer burn in a vacuum or in plasma-pure environments.
+
+
davipatury updated:
+
+
Security Records now uses Nano-UI.
+
+
+
24 February 2017
+
FalseIncarnate updated:
+
+
Corn and bananas can be properly deepfried into their special results again.
+
Rice can be properly ground into a reagent again.
+
Hydroponics trays once again are equipped with Bee-proof lids to keep unwanted pollination to a minimum. This only works if you actually toggle the lid closed though!
+
Plants age slightly slower, so your space farming should no longer feel like it outpaces a meth'd up blue hedgehog in sneakers.
+
+
Kyep updated:
+
+
Fixes blob spawns prompting players twice.
+
+
Markolie updated:
+
+
Mining pod weapons are once again functional. Compared to regular kinetic accelerators, the weak projectile has one additional range (3 --> 4). The regular projectile's damage is increased (40 --> 50) and deals more damage in pressurized environments (50% instead of 25%). The enhanced projectile is able to fire its kinetic projectile AoE against turfs and mobs.
+
Fixed an issue where it was impossible to log out from fax machines.
+
It is no longer possible to steal ID cards from identification computers/fax machine using telekinesis at range.
+
The follow link on death alarms now works.
+
Fixes an exploit where players could use the ambulance trolley to teleport.
+
The chef now properly shows a chef hat on character preview.
+
The nuclear ops game mode will no longer always result in a major crew victory.
+
Players with their face covered will no longer show their flavor text upon examine.
+
Fax machines now have an "Eject ID card" verb so you can remove the inserted ID when it is depowered.
+
Firelocks are now more lethal.
+
Firelocks now crush players standing inside them when they finish closing.
+
Firelocks can no longer be instantly opened by hand: it requires thirty seconds and will autoclose in five seconds if there is still an atmospherics alert present in the area. They can no longer be closed by hand. Heavy firelocks can not be forced by hand.
+
Atmospherics technicians can once again remotely modify all settings on air alarms through the central atmospherics console.
+
+
Purpose2 updated:
+
+
Captain's crown is now part of the random hats crate, and no longer spawns in their locker.
+
+
Twinmold93 updated:
+
+
Ability to label bloodpacks with a pen, so you can now label a bloodpack from donations without a handlabeler.
+
Bloodpacks will now change name to say if they are empty or not.
+
+
davipatury updated:
+
+
EFTPOS now uses Nano-UI.
+
Medical Records now uses Nano-UI.
+
Employment Records now uses Nano-UI.
+
+
+
23 February 2017
+
Krausus updated:
+
+
Ghost candidate alert boxes ("Do you want to play as a thing?") will now have "No" as the leftmost, default option, which you will accidentally pick when it pops up while you're trying to type, but at least you won't be stuck as the thing when you didn't actually want to be that thing.
+
+
Markolie updated:
+
+
The meteor shield satellite station goal coverage goal has been increased tenfold.
+
+
+
22 February 2017
+
KasparoVy updated:
+
+
You can now toggle on/off the gladiator helmet's face-shield with an action button. This is totally cosmetic. imgadd: Adds a bunch of new helmet sprites for Vox.
+
Slightly adjusts the Vox knight armour sprites (not the Templar armour) to look nicer with the new helmets.
+
The Admin 'Select Equipment' debug verb now appropriately equips Armalis when the 'Vox' option is selected.
+
+
+
21 February 2017
+
Crazylemon64 updated:
+
+
Autolathes can be hacked again
+
+
KasparoVy updated:
+
+
Removes rogue super-bright pixel at top of Vulpkanin Adhara hairstyle north and south facing sprites.
+
+
Kyep updated:
+
+
Deleted clown planet away mission.
+
blobs now spawn with a player in control, instantly. There is no longer a 30 second period where they exist, but nobody is controlling them.
+
blobs now get extra time after spawn, before they are announced.
+
+
Markolie updated:
+
+
Megaphones can no longer be used by mute people.
+
Rechargers will no longer recharge stacks beyond their max amount or restack 0.5 sheets.
+
Ranged guardians now have a proper one second cooldown instead of 0.1 seconds.
+
Cult can no longer soul stone manifested ghosts.
+
+
davipatury updated:
+
+
Autolathe now uses Nano-UI.
+
+
uraniummeltdown updated:
+
+
Shuttle engines should now face the correct way
+
+
+
20 February 2017
+
Markolie updated:
+
+
The chaplain on the Cyberiad map now has a one-use soulstone.
+
The chaplain's soul stone on MetaStation can now only be used once.
+
+
davipatury updated:
+
+
Shuttle Console now uses Nano-UI.
+
+
tigercat2000 updated:
+
+
The AI has a button next to radio messages to open the door closest to the speaker. ;AI, Open this fucking door!
+
+
+
19 February 2017
+
Markolie updated:
+
+
Claw games no longer eat up all glass sheets in the stack when constructed.
+
+
+
18 February 2017
+
Alffd updated:
+
+
Fixes missing entries in species/station for Vox cough and sneeze.
+
+
Crazylemon64 updated:
+
+
Centcomm has begun enforcing stricter security protocols after a recent influx of fax responses from Clown impersonators
+
Mind transfer abilities work again
+
Centcomm is no longer obnoxiously pedantic, regarding BSA deployment
+
+
Krausus updated:
+
+
End-of-round sounds will now play just in time for them to end as the server reboots, rather than starting the moment it reboots.
+
+
Kyep updated:
+
+
Added a 'take' option to ahelps/mhelps, so admins/mentors can quickly let the asker know their question is being looked at.
+
+
Markolie updated:
+
+
Vending machines, newscasters, biogenerators, plant DNA manipulators, seed extractors, bots, fax machines, photocopiers, AI slippers, cell door timers, airlocks, pipe dispensers and atmospherics machinery that open a window can now be viewed by ghosts.
+
Admins can now interact with mass driver, crematorium, ignition, light, flashers and flasher switches and door switches, as well as airlocks, windoors, firedoors and atmospherics machinery that do not open a window if they have advanced admin interaction enabled (under the "Admin" tab).
+
Slicing disposal pipes now shows a progress bar.
+
+
uraniummeltdown updated:
+
+
Shuttle engines have new sprites.
+
+
+
17 February 2017
+
Crazylemon64 updated:
+
+
Space vines now have a mutation that lets them grow in a more intelligent manner
+
+
Ported by Markolie, developed by AnturK updated:
+
+
Station Goals have been ported from /tg/. These optional goals are big projects given to the station by Central Command, requiring interdepartmental cooperation and a huge number of resources to complete.
+
Three station goals have been added: bluespace artillery construction, meteor shield satellite network and DNA vault.
+
Fixes the "Messages" tab of the communications computer.
+
+
+
16 February 2017
+
Crazylemon64 updated:
+
+
Slime people and Dionae now make sounds when coughing
+
+
KasparoVy updated:
+
+
Welding goggles and welding gas masks now properly affect your vision.
+
+
davipatury updated:
+
+
changed urnaium to uranium in wt-550 auto gun uranium magazine design
+
+
uraniummeltdown updated:
+
+
The wizard has a new spell, Rod Form, which allows him to transform into an immovable rod.
+
Ethereal beings no longer cause bananium floor tiles to squeak.
+
+
+
15 February 2017
+
Alexshreds updated:
+
+
Coughing and sneezing now plays sounds.
+
+
Ausops updated:
+
+
Internals and plasma tanks have been resprited.
+
+
Crazylemon64 updated:
+
+
Phlogiston now ignites consistently upon application
+
+
FlimFlamm updated:
+
+
New decals for boxes. Just apply a pen to change them (while they're open)!
+
+
KasparoVy updated:
+
+
You can now choose to speak anonymously in deadchat from round-start game preferences.
+
Your decision to speak anonymously in deadchat now persists between ghostings.
+
Vox tails won't change colour when other Vox spawn in anymore.
+
+
Markolie updated:
+
+
Mine bots once again only do ten damage in pressurized areas
+
+
Twinmold93 updated:
+
+
Blob Conscious Split now properly scales the requirement of blob tiles to win.
+
+
uraniummeltdown updated:
+
+
Borers now have action buttons
+
Borer names are now dependent on generation
+
+
+
14 February 2017
+
Developed by Cyberboss, ported by Markolie updated:
+
+
Progress bars will now stack vertically.
+
Progress bars will no longer be affected by lighting.
+
+
DrunkDwarf updated:
+
+
Adds a section to the Airlock menu of the RCD to allow specifying the name of the new Airlock
+
+
Fethas updated:
+
+
You can no longer put anything THAT IS ALREADY A CULTIST IN A SOULSTONE....AT ALL.
+
Readds missing beserker robe sprite.
+
Cap growth serum at 1.5
+
+
Fox McCloud updated:
+
+
Xenobiology console should be more responsive when using/exiting using it
+
Xenobiology console can now be loaded with a bag
+
Using monkey cubes on the Xenobiology console no longer makes you attempt to utilize the console
+
+
Markolie updated:
+
+
The kinetic accelerator sprite modkits now apply properly when the kinetic accelerator is empty.
+
Welding tools now once again have a proper in-hand when turned on.
+
+
+
13 February 2017
+
Crazylemon64 updated:
+
+
Achieving higher growth rates on kudzu will result in a faster-growing vine when planted
+
+
Fethas updated:
+
+
Metastation: The escape shuttle doors should no longer be security access only.
+
Metastation: Hooks up disposals door control.
+
Cyberiad: Untriggers Neca and makes the floor tiles in the emergecny wing sec area plating.
+
Cyberiad: Moves the cargo mail room table onto the otherside of the window so you can actually OPEN IT.
+
+
Fluff12 updated:
+
+
Greys can now choose to speak in wingdings or not. The Voice option is right below Species in character creation if Grey is selected - make sure you have it set to what you want!
+
+
Fox McCloud updated:
+
+
improves the tatortot sprite
+
+
Kyep updated:
+
+
Playtime requirements for IAAs have been set at 5 hours (similar to Sec Officer). Playtime requirements for Captains and AI have been increased from 10 hours to 20 hours.
+
Mech-mounted teleporters are no longer massively overpowered. They now consume a huge amount of energy to use, to the point that crew mechs with them can only use them a few times. They can no longer be spammed. Dark Gygax mechs used by nuclear operatives get a better version of the teleporter, which has around 40 uses, and is more precise.
+
Fixed several bugs related to Terror Spider webs.
+
Terror Spiders have been rebalanced. Spiders are no longer spaceproof, princes are now proper minibosses, and more.
+
Several new classes of Terror Spiders (green, white, purple, queen, mother) have been added - including types which can breed. This creates new strategy around nest defense.
+
+
Markolie updated:
+
+
Fixed a number of genetics powers not working.
+
Posibrains can no longer whisper when silenced.
+
Syndicate turrets will no longer target the Syndicate pAI found on their outpost.
+
Fixed the "Swedish" disability occasionally hiding parts of speech.
+
Mouthless players can no longer eat crayons (such as IPC's).
+
Instruments can now be interacted with while buckled.
+
Emagging a single fax machine will no longer give all fax machines access to the Syndicate destination.
+
Evidence bags will now always show the item inside of them.
+
Spacepods leaving a trail of humans instead of ion trail effects.
+
+
uraniummeltdown updated:
+
+
Nuclear Operatives can customize the Declaration of War.
+
The RSF has a unique sprite.
+
+
+
12 February 2017
+
Fox McCloud updated:
+
+
Fixes erroneous access on inner morgue door which was granting people with morgue access, access to the entirety of medical bay
+
+
Kyep updated:
+
+
added two more mining hardsuits to the mining outpost.
+
+
uraniummeltdown updated:
+
+
Whetstones have been resprited
+
Drying racks have new sprites.
+
+
+
11 February 2017
+
Markolie updated:
+
+
Ports over the remaining Lavaland loot items from /tg/ (most developed by KorPhaeron).
+
Refactors the kinetic accelerator to use modkits instead of subtypes: these unique mods (such as more range or shorter cooldown) can be purchased from the mining vendor or built by R&D or robotics (developed by KorPhaeron).
+
+
+
10 February 2017
+
Fox McCloud updated:
+
+
Fixes not being able to bloodcrawl in most sources of blood
+
Fixes slaughter demon whisper not working at all
+
Drying rack drying now properly uses NanoUI instead of a right-click verb
+
Fixes produce appearing stuck in a drying rack when it was empty
+
Fixes a few failed icon updates with the drying rack
+
+
KasparoVy, Krausus updated:
+
+
Adds the colourblindness gene. It is eye-dependent, and can be transferred from person-to-person with the eye organ.
+
Colourblindness can be detected by the advanced medical scanner just like blindness and short-sightedness.
+
Vulpkanin and Tajara can now choose to be uniquely colourblind in exchange for fantastic darksight. The default option is colour vision but low darksight.
+
Selecting mechanical or mechanically assisted eyes at character creation grants full colour vision, but standard Human darksight. This overrides the colour vision preference.
+
Mechanical(ly assisted) internal organs such as hearts and eyes are now appropriately named, and have appropriate sprites.
+
Vulpkanin and Tajara monkey-forms (Wolpins and Farwas) are incurably colourblind but have excellent darksight as they get nearly the same organs as their greater forms.
+
Increases reliability of turning into a monkey.
+
Fixes a bug with changelings lesser-forming, transforming and humanforming into a different identity.
+
+
Markolie updated:
+
+
Firelocks can now be constructed and deconstructed.
+
Firelocks no longer show a confirmation message when being opened.
+
Various map fixes (vents, scrubbers, firelocks and intercoms). Also removes the firelocks covering the windows in escape/cargo.
+
+
tigercat2000 updated:
+
+
Ported Goonstation slash /vg/ lighting. Pretty.
+
+
uraniummeltdown updated:
+
+
Quantum Pads are now buildable in R&D!
+
Quantum Pads, once built, can be linked to other Quantum Pads using a multitool. Using a Pad which has been linked will teleport everything on the sending pad to the linked pad!
+
Pads do not need to be linked in pairs: Pad A can lead to Pad B which can lead to pad C.
+
Upgrading a Quantum Pad will reduce the cooldown, charge-up time, and power consumption.
+
Quantum Pads require a bluespace crystal, a micro manipulator, a capacitor and a cable piece.
+
Events now scale better with population.
+
Enabled immovable rod, slaughter demon and morph events.
+
+
+
08 February 2017
+
Fox McCloud updated:
+
+
Grinding wheat and other products produces the proper reagents again
+
+
+
07 February 2017
+
Fox MCCloud updated:
+
+
Tank transfer valves have in-hand icons
+
Tank transfer valves with large tanks (ie: jetpacks) cannot fit in backpacks
+
+
Fox McCloud updated:
+
+
fixes xeno eggs taking damgae from disablers
+
adjusts most botany plant reagents to have "plantmatter" as opposed to nutriment
+
Blumpkins now have plasma in them
+
Fixes plant grown diona not being allied with plants and vines
+
Water coolers now dispense cups when clicking on them with a free hand
+
reagent tank dispensing amount based on the container instead of the tank
+
Fixes beaker spilling when placing a beaker into an ice cream machine
+
Adds in 100,000 unit water tanks to cargo for 12 points
+
regular water tank cost reduced from 8 to 6 points
+
Monkey cubes in boxes no longer start off wrapped
+
All monkey cube boxes at cargo are the same price
+
Fixes Nymphs not being able to cross over top of hydroponics trays
+
Diona fertilizing and weed eating is handled by clicking on the tray as a nymph rather than verbs
+
+
KasparoVy updated:
+
+
Storage implants are now checked for steal objective items.
+
+
Kyep updated:
+
+
AI holograms now transfer between holopads as the AI moves around.
+
+
uraniummeltdown updated:
+
+
Engineering and Science crates now have new sprites
+
Changelings can recall the memories of an absorb victim
+
Changelings will recall some speech of their absorb victims
+
You can now create floor tiles from minerals. Be careful around plasma and uranium floors though.
+
+
+
06 February 2017
+
Fox McCloud updated:
+
+
Fixes traitor banana peels having no sprite
+
Stunprods are constructed with igniters instead of wirecutters
+
Stunprods will spark when you stun someone with them
+
Expands the amount of cryodorm pods
+
+
KasparoVy updated:
+
+
IPC names with numbers now load correctly from SQL.
+
+
Kyep updated:
+
+
Autoprocess cloners will no longer clone people who cryo and ghost out, or otherwise deliberately remove themselves from the round.
+
Dead miners in UO45 away mission are no longer naked.
+
ERT and SST shuttle consoles now require the appropriate access to use.
+
+
uraniummeltdown updated:
+
+
You can interact with an ore box by using an advanced mining scanner on it.
+
Xenobiology Console is now constructible, board has been added to the Circuit Imprinter.
+
Plasmaman IAA/Lawyers now have a unique suit.
+
AI control beacons are a new item created from the exosuit fabricator. When installed into a mech, it allows AIs to jump to and from that mech freely. Note that malfunctioning AIs with the domination power unlocked will instead be forced to dominate the mech.
+
Changelings have a new default ability: Hivemind Link. This lets you bring a neck-grabbed victim into the hivemind for a few minutes. You can talk to your victims and perhaps persuade them to help you, give you intel, or even a PDA code. Victims in crit will be stabilized.
+
Added new AI core sprites from TG
+
Added Vox rad suit, bombsuit hood, paramedic EVA suit sprites from /vg/
+
You can click AI displays as an AI to change them
+
+
+
05 February 2017
+
Fethas updated:
+
+
Brings unholy water in line with its description.
+
+
Fox McCloud and Core0verload updated:
+
+
Dramatically overhauls the botany system; features more user friendly gene modification methods, more control over attributes and reagents in your plants, and more
+
Adds in drying rack for drying growns for smoking with rolled papers
+
Store spare seeds in the seed extractor
+
Adds in cloth; make clothing, satchels, backpacks, duffelbags and more.
+
Upgrading hydroponics trays impacts how quickly plants degrade
+
Bees slightly more effective at increasing plant yields
+
Overall growth rate of plants dramatically increased
+
Adds in the ability to construct bonfires with wooden logs; perfect for keeping you our your fellow spessman warm---forever
+
Adds in a few new bartender drinks and recipes, such as chocolate pudding, vanilla pudding, and pumpkin spice
+
Can now wear some flowers/ambrosia in your hair
+
Combining genes form different plants has unique effects (For instance, the battery gene with the recharging gene allows you to make insanely potent batteries)
+
Vines are now purely handled by the Kudzu plant
+
Botanists have been given morgue access
+
+
Ported by Markolie, developed by KorPhaeron and others from /tg/. The Hierophant was developed by ChangelingRain. updated:
+
+
Megafauna and their rewards have been added to the code. These are not on the map yet.
+
Fireball is now a targeted spell instead of a dumbfire spell.
+
Most spells, wands and staffs now have unique spell sounds.
+
Added a new nullrod type, the "spellblade".
+
Added bows, arrows and quivers. Currently only available for admins.
+
Added cockroaches. Currently only available for admins.
+
Added support for BYOND medals. Currently disabled.
+
Added a number of Lavaland objects (flora, basalt, food and stacks). Currently only available for admins.
+
Earmuffs can now be produced in autolathes.
+
Syndicate gun turrets are now subtypes of regular turrets: this makes them controllable with Syndicate ID's and improves their targeting.
+
Diona and Shadow People now receive a warning when they're not exposed/exposed to light.
+
The sniper AP rounds that Nuke Ops can purchase now have a chance of dismembering limbs.
+
Shadow People can now switch their night vision properly.
+
Certain messages in chat weren't showing up in their proper (large) size, such as the Nar'Sie spawned message. This has been resolved.
+
+
uraniummeltdown updated:
+
+
Supply ID skin is now selectable in the Agent ID and ID Computer
+
+
+
03 February 2017
+
DrunkDwarf updated:
+
+
Set the Mr Chang's vending machine to be refillable
+
Added a Supply Crate to the Vending section of the Cargo Request Console for Chinese Refill Canisters
+
+
+
02 February 2017
+
Alexshreds updated:
+
+
Deconstructing closets yields the proper amount of metal
+
+
Kyep updated:
+
+
Using the 'summon narsie' rune as cult, when you don't have the objective to do so, is now punished by the cult's god. Just as using the 'call forth the slaughter' rune, when you don't have the objective to do that, is already punished.
+
+
uraniummeltdown updated:
+
+
Engineering Cyborgs now have a digital copy of the station blueprints.
+
+
+
31 January 2017
+
Ar3nn updated:
+
+
cursed cluwne mask now allows internals to be fed through it
+
+
FalseIncarnate updated:
+
+
All requests consoles can print off a single-use, pre-tagged Shipping Package for sending a single item via disposals to a destination of your choosing.
+
Shipping Packages can be used to tag packages wrapped with wrapping paper, in case you don't have access to cargo's destination tagger.
+
Requests Consoles log the printer and destination of all shipping labels printed from that particular console. There currently is no way to clear your mailing history, so mail responsibly.
+
+
Fethas updated:
+
+
Fixes a rune runtime.
+
+
FlattestGuitar updated:
+
+
adds an admin-only laser carbine
+
+
uraniummeltdown updated:
+
+
Your game window will now flash on receiving Admin PMs, being revived, and ghost roles. You can disable this in Game Preferences.
+
+
+
30 January 2017
+
Alexshreds updated:
+
+
No more double traitor 241 Special
+
+
+
29 January 2017
+
uraniummeltdown updated:
+
+
You can now take items directly out of a storage item in your backpack.
+
+
+
27 January 2017
+
Alffd updated:
+
+
Adds missing hat and shoe sprites that were inadvertently deleted.
+
+
Fox McCloud updated:
+
+
Adds in stungloves (inaccessible to players)
+
+
uraniummeltdown updated:
+
+
Injecting a rainbow slime extract with blood will create a consciousness transference potion.
+
Injecting a metal slime extract with water will create 15 sheets of glass and 5 sheets of reinforced glass.
+
Slime potions now check for proximity.
+
+
+
26 January 2017
+
FalseIncarnate updated:
+
+
Plasma dust can now be used to rig lights and power cells, like the plasma reagent, with explosive results.
+
+
Fethas updated:
+
+
Adds two new holy weapon skins for people who belive in ghosts and worshipers of the silentfather.
+
+
FreeStylaLT updated:
+
+
AI sat transport tubes are no longer misaligned
+
+
+
25 January 2017
+
FlattestGuitar updated:
+
+
Fixes shadowlings thrall scaling
+
+
scrubmcnoob updated:
+
+
Shadowling Thrall count now scales to a max of 25.
+
Shadowling Thralls lose lesser glare
+
+
+
23 January 2017
+
FalseIncarnate updated:
+
+
Returns the ability to remove vacant soil with shovels and spades, and adds the ability to dig up plants in soil to remove them instantly.
+
+
Stratus updated:
+
+
NT Enforcer .45 pistol.
+
.45 and 9mm rubber bullets.
+
New shotgun ammo boxes.
+
+
+
18 January 2017
+
AndriiYukhymchak updated:
+
+
multitool can now be used to swap directions of TEG's circulator
+
+
Fethas updated:
+
+
Adds in the check numbers proc to converting, I missed it from VG.
+
Removed a redundent sacrefice objective check AND fixed the sacrfice objective check so it actually PICKs on mode start.
+
changed the color of manfested ghost humans to grey...huehuehuehuehue(serously it helps tell them apart better).
+
mass convert objective now picks between 9 and 15 as a target instead of based on round pop..cuase 30 MIGHT be a bit much.
+
adds admin cult tools Bypass phase (missed this off vg) and cult mind speak(YOUR GOD IS DISPLEASED GIT GUD). Might be better in secret panel but it confuses me.
+
Removes errent invisaible animals from the narnar escape shuttle template.
+
+
KasparoVy updated:
+
+
Characters with the obese disability are now fat beneath their clothes.
+
+
Markolie updated:
+
+
Admin announcements are no longer sent to player in the lobby.
+
Regular announcements can now only be heard if you the player is alive, not deaf and in range of an enabled radio.
+
+
+
17 January 2017
+
Crazylemon64 updated:
+
+
Joined Souls works now
+
Scribing the end rune now no longer is impossible
+
+
Krausus updated:
+
+
Fixed the exciting new emoji breaking chat entirely for IE8 users. :clap:
+
+
+
16 January 2017
+
Alexshreds updated:
+
+
Revenants can now breathe in space.
+
Can no longer exploit RCDs for metal
+
+
Krausus updated:
+
+
You can now use pills and patches on people with full bellies.
+
The Randomized Character Slot option now actually works.
+
+
+
15 January 2017
+
Funce updated:
+
+
dual-port air vents can now be unwrenched
+
+
TullyBurnalot updated:
+
+
Broken and Burned bulbs are no longer forced on with every overload.
+
Only non-broken and non-burned bulbs actually break and spark on an overload.
+
Fixes a single syntax error in the Shadowling Ascendant descriptive text.
+
+
+
14 January 2017
+
Crazylemon64 updated:
+
+
Bibles can now reveal runes as they did before
+
+
Krausus updated:
+
+
Players will no longer be informed of what cult may or may not exist on round start.
+
+
+
13 January 2017
+
DarkPyrolord updated:
+
+
Removes the joy mask
+
+
TullyBurnalot updated:
+
+
Cyborg tools (and other non-droppable tools) cannot be transferred to an open, empty Display Case
+
Jobs receive links to SOP and their Department SOP at roundstart. Space Law and Legal SOP links added to Security members, Magistrate and IAAs
+
+
uraniummeltdown updated:
+
+
You can see what sting you have equipped as changeling.
+
All species except IPCs can now be changelings and be affected by their genetic abilities.
+
Arm Blade can now pry open powered airlocks
+
Transformation Sting now costs 3 points and requires 50 chemicals
+
You can no longer transform people into Vox with Transformation Sting.
+
Removed Engorged Chemical Glands, Changelings now have the ability by default
+
+
+
12 January 2017
+
TullyBurnalot updated:
+
+
Graffiti now have hidden (Admin-only) fingerprints added to them
+
+
+
11 January 2017
+
Crazylemon64 updated:
+
+
Ghosts can now see if they're allowed to respawn or not at a glance
+
Cyborg sight modes are now actions, instead of items
+
Mining drones can now use meson sight again
+
It's no longer opposite day for the karma reminder preference
+
+
Lady Luck updated:
+
+
office laptops are now traversable
+
+
Markolie updated:
+
+
simple_animals now have an attack cooldown when attacking mechas.
+
+
uraniummeltdown updated:
+
+
Atmos Console Boards now show in Computer Boards of Circuit Imprinter
+
+
+
10 January 2017
+
Crazylemon updated:
+
+
Giant spiders now have their own role pref
+
+
Crazylemon64 updated:
+
+
pAIs can now adjust their radios
+
pAIs can now more reliably hear nearby whispers
+
pAIs can now whisper while inside a PDA
+
pAIs can no longer change their icon from being dead, while dead
+
Non-respawnable players are no longer prompted to submit a pAI when the opportunity is available
+
Borg sight modules work again
+
+
Fox McCloud updated:
+
+
different alert levels for how full you are from starving all the way to fat
+
There is now satiety and nutrition; being satisfied and full has a number of positive benefits; being unsatisfied and hungry has negative side effects
+
Some foods have vitamins in them which provide little nutrition, but greatly increase your satisfaction
+
Some food reagents have had their nutritional values tweaked
+
reagent numbers tweaked on most food items
+
Fixes the floral gun not properly working on Diona
+
+
TullyBurnalot updated:
+
+
Wand of Death now reliably kills people by adding 300 Burn Damage. This includes self-casting
+
Minor flavour text visible on impact of target
+
pAI HUDs are now visual-only, restricting their access to editable records
+
+
pinatacolada updated:
+
+
IV drips now have adjustable rates
+
+
uraniummeltdown updated:
+
+
Mimes can now choose name on entry just like Clowns
+
Added many new costumes to the Autodrobe!
+
+
+
09 January 2017
+
Crazylemon64 updated:
+
+
The operating table now checks for both either `lying` or `resting` - so surgery will work no matter what on unconscious people lying on your table.
+
+
Kyep updated:
+
+
Antags should no longer get bounced to lobby at round start in certain rare situations.
+
+
+
07 January 2017
+
Markolie updated:
+
+
False walls now block atmospherics, unless it's open.
+
+
+
06 January 2017
+
Crazylemon64 updated:
+
+
pAI UIs no longer break
+
The chem dispenser's UI now displays the remaining energy again
+
Shuttles no longer make buckling useless
+
You should no longer go mute randomly
+
You can now opt out of all requests on a role for a round
+
Morgue trays now have descriptions that correspond to each of the morgue light states
+
Waking up no longer auto-cancels resting.
+
+
Fethas updated:
+
+
ports parts TG neo-oldcult rscadd:Ports parts of cult from VG
+
+
KasparoVy updated:
+
+
Grey sprites have been tidied up and no longer have any random pixels hanging off.
+
Grey species-fitted tattoo sprites and the last Vox species-fitted tattoo sprite.
+
+
Krausus updated:
+
+
SDQL2 can now directly manipulate clients.
+
+
Kyep updated:
+
+
Mobs in vents no longer see vents/scrubbers as unwelded when they are welded, and vice versa.
+
+
+
03 January 2017
+
KasparoVy updated:
+
+
The Vulpkanin Anita hairstyle no longer has rogue extra-bright pixels.
+
+
Kyep updated:
+
+
Added tracking for how much playtime each player has.
+
Added the ability to lock jobs based on playtime. E.g: must play for 10 hours to unlock HoS.
+
+
+
02 January 2017
+
KasparoVy updated:
+
+
Particle Accelerators ordered from Cargo can now function.
+
Wrenching powerless machines in a powered area will no longer require you to toggle the lights (or whatever you did before to sort this).
+
+
Krausus updated:
+
+
The syndicate nuke and pinpointer locker will once again spawn into their ship, rather than into space near the station.
+
+
Kyep updated:
+
+
Terror Spiders can no longer create more than one web on a tile.
+
+
+
01 January 2017
+
Kyep updated:
+
+
Added basic, AI-less versions of some Terror Spiders.
+
+
+
31 December 2016
+
Crazylemon64 updated:
+
+
The home gateway now will send ghosts to the other end by default, now
+
+
+
30 December 2016
+
Crazylemon updated:
+
+
The shuttle manipulator can now only be used by admins
+
+
FalseIncarnate updated:
+
+
Adds Nano-Mob Hunter GO! PDA game cartridges and related stuff. Grab a cartridge from the cartridge vendor or loadout and join in on the hunt!
+
Adds Nano-Mob Hunter GO! Battle Terminals to the Holodeck and a Nano-Mob Hunter GO! Restoration Terminal to medbay's lobby.
+
+
Fox McCloud updated:
+
+
Fixes cyborg cryo oddities
+
+
KasparoVy updated:
+
+
Taking off noir glasses while noir mode is on will now give you your colour vision back.
+
+
+
29 December 2016
+
Fethas updated:
+
+
Alternate shuttle/ferry template system from TG
+
Shuttle Manipulator
+
Better shuttle kills
+
+
Markolie updated:
+
+
The camera console has been refactored so there's no longer a delay when switching cameras.
+
The camera console should no longer lag for several seconds.
+
+
+
25 December 2016
+
FalseIncarnate updated:
+
+
Santa's back and with-holding all your presents! Head through the gateway and show the Fat Man the strength of your holiday spirit (and advanced weaponry, you'll be needing that)!
+
+
KasparoVy updated:
+
+
Cameras will no longer be able to take photos of stuff outside your line of sight.
+
Cameras will now render disguises as you see them.
+
+
+
23 December 2016
+
Crazylemon64 updated:
+
+
Welding overlays now update instantly
+
Being inside various structures will now obscure your vision
+
+
Fox McCloud updated:
+
+
Fixes X-Ray not doing anything
+
Fixes nightvision not granting what its name implies
Characters will now be correctly assigned their species' genetic quirks at spawn.
+
Cloning will now correctly assign a characters species' genetic quirks.
+
Changing a character's species (via C.M.A. or whatever might call the set_species proc) will now correctly assign their species' genetic quirks.
+
+
Markolie updated:
+
+
Ruins no longer trigger power alarms.
+
+
+
20 December 2016
+
TullyBurnalot updated:
+
+
Neurotoxin Spit now causes the spitter to move in space
+
Proximity Wet Floor Sign Mines can no longer appear in Surplus Crates
+
+
+
14 December 2016
+
Fox McCloud updated:
+
+
Fixes the personal crafting cost of ED-209's being too expensive
+
+
+
13 December 2016
+
TullyBurnalot updated:
+
+
Medbots no longer run after injured mobs if buckled. They also inform nearby players of this
+
+
+
12 December 2016
+
Kyep updated:
+
+
Xenomorph resin walls no longer take damage from disabler beams. Only proper BRUTE or BURN damage hurts them now.
+
+
TullyBurnalot updated:
+
+
Throwing mobs behind you force moves them to behind you before actually throwing them, preventing throw-shoving
+
+
+
09 December 2016
+
KasparoVy updated:
+
+
You can now define whether a hair style will cover glasses or not. Only long hair styles should cover glasses (default behaviour).
+
You can now define whether a facial hair style/head accessory will be rendered on top of hair or not.
+
Glasses no longer render on top of all hair styles, only sufficiently short ones.
+
+
+
08 December 2016
+
Kyep updated:
+
+
Ensures cryo pods will properly auto-eject people whose organic parts (limbs) have been healed, but who still have damaged mechanical limbs.
+
Disabler shots no longer damage mechs.
+
On impact, both taser and disabler shots now produce a message saying that the mech is undamaged by them, instead of a message saying they 'hit'.
+
Fixed runtimes created when SIT, ERT, and some other mobs are spawned.
+
Fixed a bug causing SITs to be spawned with one less person than desired in some cases.
+
+
+
07 December 2016
+
Markolie updated:
+
+
Verbs have been cleaned up: all karma verbs can now be found under "OOC" instead of "Special Verbs". Most admin verbs have been moved out of "Special Verbs" as well.
+
+
TullyBurnalot updated:
+
+
Unpowered Mining Vendors no longer accept IDs
+
Ore Redemption Machine and Mining Vendor can now be deconstructed if unpowered
+
+
+
06 December 2016
+
Markolie updated:
+
+
The track button on the AI crew monitor now works.
+
Permanent door electrification by alt-clicking a door as an AI or setting it manually now works again.
+
+
+
05 December 2016
+
KasparoVy updated:
+
+
Resolves an issue where cloned vampires could no longer drain blood, burn in the chapel or use their powers properly.
+
+
+
04 December 2016
+
KasparoVy updated:
+
+
Resolves an issue with changeling regenerative stasis where changelings who initiated it while alive and died during the waiting period did not come back to life. Now they will, as intended.
+
+
+
03 December 2016
+
Kyep updated:
+
+
the anti-ERP warning message on PDA message consoles is now accurate.
+
+
+
01 December 2016
+
Crazylemon64 updated:
+
+
Cryo tubes no longer let you excessively multiply the efficiency of touch chems
+
+
KasparoVy updated:
+
+
The character preview icon in character creation is now more detailed and less blurry.
+
ID cards now show tails, body accessories and tail markings correctly.
+
+
Twinmold93 updated:
+
+
Pilots of spacepods will no longer be sent to the void when the space pod is destroyed in any method.
+
Pilots of spacepods will now get the same warnings for damage/core destruction that passengers get.
+
+
+
29 November 2016
+
KasparoVy updated:
+
+
Head, body and tail markings are now loaded correctly from genes (UI).
+
Changes to a person's skin-tone gene are now immediately apparent.
+
+
+
28 November 2016
+
Allfd updated:
+
+
Fixes an issue with the processing of GitHub changelog emoji in the php webhook.
+
+
Crazylemon64 updated:
+
+
The RCD no longer shall work as a remote permissions control
+
+
KasparoVy updated:
+
+
Pressing the light switch in one OR will no longer turn off the lights for both.
+
The fire alarms in each OR now work independently of each-other.
+
The second operating room now has its own APC and wiring.
+
+
+
26 November 2016
+
Fox McCloud updated:
+
+
Fixes faint emote doing nothing
+
Fixes Mickey Finn's Special Brew not functioning properly/not making you fall asleep
+
+
+
23 November 2016
+
Fethas updated:
+
+
Fixes human jetpacks..maybe...
+
+
FlattestNerd updated:
+
+
the e20 will now get logged when it goes BEWM, as it should.
+
+
Fox McCloud updated:
+
+
Fixes double-breaking news newscaster
+
+
+
22 November 2016
+
KasparoVy updated:
+
+
You now stutter when you're in shock/crit and when you've got the nervous disability as you used to.
+
+
Twinmold93 updated:
+
+
Runtime caused by lack of settlers in the Orion arcade game.
+
+
+
20 November 2016
+
KasparoVy updated:
+
+
The DNA SE injectors one can find in the abandoned mining crates now correctly activate/deactivate the powers they may contain.
+
+
+
15 November 2016
+
KasparoVy updated:
+
+
Adding cable to multiple computer frames at the same time while not having the correct amount of cables will no longer cause busted coils with a negative number of cables.
+
+
+
13 November 2016
+
Fox McCloud updated:
+
+
Fixes BSA having peculiar results.
+
+
+
07 November 2016
+
Crazylemon updated:
+
+
Status effects should work a little more consistently now
+
+
Crazylemon64 updated:
+
+
The mech-mounted plasma cutter can now be constructed again
+
Space pod lasers can now be constructed again
+
+
Fox McCloud updated:
+
+
Fixes hunters not being weakened when crashing into a shield/wall
+
Fixes xeno stuns half the time intended
+
Fixes stopping, dropping, and rolling not properly weakening Xenos/Hulks
+
+
KasparoVy updated:
+
+
Fixes a bug where changing your alt head required two icon updates to show.
+
Fixes a bug where you couldn't choose head marking styles that would ordinarily be available regardless of your alt head.
+
Fixes a bug where Tajara couldn't choose undergarments.
+
Resolves an issue with the Vulpkanin Jagged hairstyle missing a pixel.
+
+
Twinmold93 updated:
+
+
Fixes a runtime issue caused by using the detective's scanner on the space hotel cleaver.
+
Scrubber pipe missing segment behind the operating theatres.
+
+
+
23 October 2016
+
KasparoVy updated:
+
+
Refactors markings. Now split into head, body and tail markings.
+
Refactors morph again. Changes made while morphing are now reflected instantly on your sprite.
+
Darkens Vulpkanin and Tajara for improved colour fidelity. Species base colour changed to compensate. Add 27 to R, G and B values if Vulp, 15 if Taj to keep the same colour on your character.
+
Darkens Vulpkanin facial fur patterns for improved colour fidelity. Add 23 to the R, G and B values of your facial hair/head accessory to keep the same colour on your character.
+
Darkens Unathi frills and horns. Add 27 to the R, G and B values of your frills and 21 for horns to keep the same colour on your character.
+
Vulpkanin tails are now split-rendered. Tails overlap hair when facing north, but are overlapped by hair when facing all other directions. No other differences, only affects the fluffy husky tail.
+
The heads of tiger markings have been isolated and can now be coloured independently.
+
Hair can now cover facial hair, and glasses are no longer covered by facial hair and head accessories. Means that two-piece Vulpkanin facial fur patterns won't almost entirely cover whatever glasses they're wearing.
+
Tajaran head and facial hair have been darkened. Add 28 to the R, G and B values of your Tajara head/facial hair to keep the same colour on your character.
+
Vulpkanin head hair and one facial hair style has been darkened. Refer to PR notes for darkening factors.
+
The HAS_MARKINGS flag now represents all marking locations. The HAS_location_MARKINGS flags are for specific locations (head, body, tail).
+
Improves the quality of some Vulpkanin/Tajara/Unathi mask sprites.
+
Naked Humans and Skrell will no longer have exposed flesh poking out their wrists when facing east or west. Male Humans now no longer lack a butt pixel when facing east or west.
+
Mutated limbs now render correctly as soon as they're mutated.
+
Mobs will now correctly appear as fat/skinny.
+
Species with TAIL_OVERLAPPED will no longer wag tail at max speed when facing north.
+
Species with TAIL_OVERLAPPED and body accessories won't crash the game when they wag.
+
Tiger Head and Face markings adjusted so they don't look ugly on certain species' ears.
+
Fixes issue where Unathi dorsal stripe didn't render.
+
Tajaran ears are no longer in their hair sprites, but on their actual heads.
+
The adminbus body accessory now overrides the TAIL_OVERLAPPED flag and will now be rendered correctly on a body regardless of species bodyflags.
+
Changing a person's species via CMA will no longer result in a mob with all the same cosmetic attributes as the old species.
+
Dressers now have species fitting checks for undergarments. Drask are now able to wear undershirts and underwear like they were originally meant to.
+
Adds some head markings for Tajara and Vulpkanin.
+
Adds body marking(s) for Tajara, Vulpkanin, Unathi and Drask.
+
Adds tail markings for Vox and Vulpkanin.
+
Adds 5 Tajaran hairstyles.
+
Adds a tweaked version of an existing Vox hairstyle. Shouldn't clip with certain jackets as much.
+
Adds a hairstyle for Humans, Unathi and Vulpkanin.
+
Adds a facial hairstyle for Vulpkanin.
+
Adds secondary hair (head and facial) themes. Skrell can now colour their tentacle cloths independently, the beads in the Tajaran/Hippie braid hairstyles can be coloured and the same with the webbing in Unathi frills. Can be changed at nanomirrors, via morph and CMA.
+
Adds alternate heads. Unathi can now choose a head with a sharp snout. Can be changed via morph and CMA.
+
Helper procs to convert a hex colour into either R, G, or B.
+
Markings, body accessories, head accessories, alt heads and their colours (if they have colours) can now be randomized at the character preferences screen.
+
Adds a system that attempts to fit mobs with alternate heads with appropriate mask sprites. The sprites just need to be suffixed with the alt_head suffix in sprite_accessories.dm.
+
Adds mask sprites tweaked to fit the new Unathi alternate head to go along with the new alt. head mask fitting system.
+
+
+
15 October 2016
+
Crazylemon64 updated:
+
+
The R&D console should now no longer freeze on the "Syncing Database" message or whatever.
+
Borg coolers and SMES boards can be made again
+
Maroon now works
+
+
FlattestGuitar updated:
+
+
pAIs no longer turn into debris when wiped
+
SNPCs no longer get targeted by assasinate objectives
+
fixes a hallucination runtime, actually making one more aspect of being high as f*** work for the first time in ages
+
NODROP items will no longer attempt to be dropped if your hand is broken
+
+
Fox McCloud updated:
+
+
Cloners will now put you inside the cloned body when it is fully grown as opposed to initially created
+
Examining a cloner will tell you the clone progress
+
Observers can now see a visual countdown of the cloning status progression
+
Atmos grenades cost increased from 6 to 11
+
Mice now have sprites when worn
+
Fixes various ghost alerts having barely visible icons
+
Fixes items being in two locations at once when loading things into the bio-generator or reagent grinder.
+
+
GeneralChaos81 updated:
+
+
Ability to place and remove conveyor belts and levers.
+
+
KasparoVy updated:
+
+
Botany, viro and xenobio bottles will no longer be invisible.
+
+
Krausus updated:
+
+
Fixed full chat panes scrolling unpredictably when trying to view old messages.
+
Fixed camera monitors immobilizing you if you reconnect while using one.
+
Fixed selecting datum types through SDQL2 never returning any datums.
+
+
+
16 September 2016
+
Aurorablade updated:
+
+
*fart now has newtonian move if you have the Superfart power
+
+
Coldflame updated:
+
+
Adds three new variants of 10mm ammunition, AP, HP, and Incendiary. Currently admin-only.
+
+
Crazylemon64 updated:
+
+
Research data disks now have a description and name attached to them automatically, to make working with them less obnoxious.
+
Loading design disks now has a sound effect.
+
You can no longer feed non-design disks into the autolathe and destroy them on accident.
+
+
DaveTheHeadcrab updated:
+
+
Due to budget cuts expensive fax machines have been replaced with cheaper versions in some departments. Only essential personnel can fax Central Command. See your local IAA for details.
+
+
FlattestGuitar updated:
+
+
Added emergency nitrogen and plasma tanks, you can find two of each in the medical storage
+
+
FreeStylaLT updated:
+
+
Updated Metastation's AI Sat, brig and escape shuttle
+
Updated other Meta areas to match most recent build. (Chapel, some maint, etc. - minor changes.)
+
Updated Cyberiad's AI Sat to latest tg version, lots of changes there - basically an entirely new Satellite.
+
+
IcyV updated:
+
+
Adds new bottle sprite
+
Fixes many bottles being locked to a single icon
+
Buckets can be worn as hats.
+
+
Improvedname updated:
+
+
Adds 4 epinephrine autoinjectors to nanomedplus vending machines
+
+
KasparoVy updated:
+
+
Adds a Science departmental beret that you can obtain via the loadout system.
+
+
Krausus updated:
+
+
Fixed species-restricted items sometimes failing to "equip" to restricted species' non-equipment slots.
+
Players using very old versions of Internet Explorer will now receive explicit warnings that they're not supported.
+
View Variables will now consistently view the variables of what it's intended to.
+
Admins can now use the 'msay' command to speak directly to all mentors.
+
Added a new command, "Toggle Mentor Chat", to give mentors temporary access to 'msay'.
+
Fixed never being able to properly respond to a PM from a stealthed admin.
+
+
Kyep updated:
+
+
SST and SIT now have their own radio frequency.
+
+
LittleBigKid2000 updated:
+
+
The God Emperor of Mankind disk now works properly
+
+
TheDZD updated:
+
+
Xenomorph hunters' leap ability is now always blocked by shields rather than only 50% of the time.
+
Xenomorph hunters' leap ability being blocked now stuns them as if they had hit a wall. The leap still goes on a 3 second cooldown as normal.
+
+
Ty-Omaha updated:
+
+
Adds fluff item "Tacticool EyePro"
+
+
+
01 September 2016
+
Crazylemon updated:
+
+
Dying of low blood is no longer capable of causing eternal death
+
Having your body brought back to life will no longer break your health doll
+
+
monster860 updated:
+
+
Fixes hotel SNPC's getting access that they shouldn't get.
+
+
+
29 August 2016
+
Crazylemon updated:
+
+
You can now mend incisions after having cut open someone's ribcage.
+
Abductor surgery works again
+
Face repair surgery works again
+
The `to_chat` messages are now more descriptive when given a bad target
+
Admins can now VV by a ref string, directly via a verb
+
VV now builds its HTML using lists, making it much faster to open
+
+
DaveTheHeadcrab updated:
+
+
Upgrades the newscaster's liquid paper printing apparatus. Newspapers printed are higher quality now.
+
+
Fox McCloud updated:
+
+
Mining Drones can now toggle meson vision on or off, a light, switch attack modes, or even drop their own ore
+
Ash storms no longer impact sheltered areas and mining mobs are immune to ash storms
+
Adds in two new end-round sounds
+
Fixes drones not being able to bump open doors
+
+
Fox McCloud and KorPhaeron updated:
+
+
Adds in mining shelters
+
Adds in a few more dice types and ensure dice are packed in bags and not pill bottles
+
+
FreeStylaLT updated:
+
+
Added additional coating to Turbine room.
+
Fixed leftover vent in Brig Physician's office
+
Fixed missing coated rwalls in Incinerator
+
+
Krausus updated:
+
+
Girders are no longer bulletproof.
+
Changelings' Swap Form ability now actually deducts its cost upon use, and shouldn't arbitrarily fail to work properly.
+
Fixed setting status display alerts through communications consoles.
+
+
Kyep updated:
+
+
Fixes 'SSD!' warning appearing in attack logs for admins, when the target player was dead and had ghosted out of their body
+
+
TheDZD updated:
+
+
Bookcases no longer force you to take out a book after clicking them
+
Fixes assorted things logging attacks incorrectly.
+
+
TullyBurnalot updated:
+
+
AIs can no longer interact with nuclear bombs (Syndicate-brand included). AIs can still see the countdown
+
Mobs without appendixes can no longer contract appendicitis
+
Holosigns cannot be pulled around
+
+
+
19 August 2016
+
Crazylemon updated:
+
+
pAIs should now save
+
+
FalseIncarnate updated:
+
+
Repairing burn damage to robotic limbs now consumes cable in the process. Each length used repairs 3 burn damage, up to 15 damage per click.
+
Repairing brute damage to robotic limbs now uses 1 fuel per repair (click). Heal amount unchanged.
+
Self-repairing with cables or welders now incurs a 1 second delay between click and heal completion. Being repaired by a friend is still no delay (but requires a friend).
+
+
Fox McCloud updated:
+
+
Adds in the Kinetic Smasher as a mining purchase
+
Fixes slap emote text being the wrong partial color
+
Fixes the attack text of simple animals attacking human mobs
+
+
IcyV updated:
+
+
Adds in an amount of new graffiti
+
Fixes the issue of other graffiti only being able to be done in black.
+
+
Krausus updated:
+
+
Flavor text and records are no longer horrifically butchered when saved in the database.
+
+
TheDZD updated:
+
+
Lowered genetic instability damage thresholds by 5 across the board. Effectively meaning that you can have one additional minor power without shifting into the next threshold.
+
Lowered the rate at which damage scales with instability, and the decreased upper cap on each damage type.
+
The base activation probability for powers is now 100%, rather than 45%. Abilities affected include everything except Cloak of Darkness, Chameleon, No Breathing, Hulk, Telekinesis, and X-Ray Vision, which all have their own independent activation chances (varying from 5% to 10%).
+
Increases activation chances of TK (10% to 15%), No Breathing (10% to 25%), Cloak of Darkness (10% to 25%), Hulk (5% to 15%), X-Ray Vision (10% to 15%), and Chameleon (10% to 25%).
+
+
+
18 August 2016
+
Alexshreds updated:
+
+
pAIs can see the crew manifest again.
+
Engineers and Atmos Techs have access to the ORM
+
+
Ar3nn updated:
+
+
dusting playermobs now generates remains fitting for their race.
+
+
Chakishreds updated:
+
+
You can now click on objects in a gassy room at the expense of ninja floors.
+
+
Chopchop1614 updated:
+
+
fixes transformation sting not working.
+
transformation sting now checks if the target has DNA or not
+
+
Crazylemon updated:
+
+
Alt+Click should be quicker now
+
The Alt+Click panel vanishes only when you alt click a turf distant from yourself
+
Adds `json_to_object_arbitrary_vars`, a proc intended for use with SDQL
+
Eye color is tracked on the eyes only, instead of on the body.
+
The CMA panel no longer runtimes when you change species.
+
Deserializing a human now preserves hair and eyes.
+
Associative lists in VV now display properly again
+
Admins can now click on the DI panel buttons to debug the corresponding controller in VV
+
Fat people are now fat when naked.
+
Encased mobs can now examine
+
+
Crazylemon64 updated:
+
+
Makes teleportation checks more consistent, which will ensure that teleporting in the away mission no longer works.
+
People on the space ruins level no longer count as dead for assassinate objectives.
+
Space border turfs will now regain their destination when over-written and replaced on the edge of the map
+
The space manager will no longer runtime if a space ruin writes on the edge of the map
+
+
DaveTheHeadcrab updated:
+
+
ERT gloves reverted to how they used to be.
+
+
FalseIncarnate updated:
+
+
WOLOLO! Traitor Chaplains can now WOLOLO with the new Missionary Staff and Robes. WOLOLO!
+
+
Fethas updated:
+
+
The whitelist will respect addons better, didn't even have to make a ban appeal..
+
+
FlattestGuitar updated:
+
+
Detective's coolness variable cranked up to 14.5, they will no longer vomit over corpses.
+
Now you're less likely to vomit over a corpse if you're a normal human being.
+
golems now have their master saved in attack logs
+
+
Fox McCloud updated:
+
+
Adds in formal captain's uniform and armor
+
Adds rapier to captain's locker
+
Adds lace up shoes to captain's locker
+
Adds crown to captain's locker
+
Dramatically speeds up conveyor belts
+
Appendicitis and Disease Outbreak events will no longer impact clientless mobs
+
Fixes bandolier being invisible on spawn
+
Removes the jukebox from the bar
+
Detective Scanner, Fedora Tipping, Pontificating, and Cap Flipping are now action buttons
+
Cane Gun and NT Rep's cane now acts as actual canes
+
+
FreeStylaLT updated:
+
+
Fixed missing space transition tiles in emergency shuttle transit
+
Fixed lack of prisoner access to lower part of labor camp shuttle
+
Changed UO45's and MO19's away missions' external tiles to just airless ones.
+
Changed MO19's exterior to be more rock than ground, this is to make Linda cry less when this mission is passed.
+
+
General Chaos updated:
+
+
Ports TG's mech bay recharger code.
+
+
IcyV updated:
+
+
Adds an exploding chameleon flag for traitors.
+
+
KorPhaeron and Fox McCloud updated:
+
+
Merges Malf AI into traitor AI
+
Malf AI's starting CPU reduced from 100 to 50
+
Hacking APCs gives 10 additional CPU
+
Hacking APCs throws an alert to the AI when it's hacking that automatically clears when hacking is complete (sounds too)
+
Traitor AI's start off with a syndicate headset
+
Adds doomsday device module for AI's for 130 CPU; when activated, it will purge the station of all life if the AI is not destroyed after 7.5 minutes
+
Adds in AI upgrade modules which allows you to giving hacking abilities to the AI or allow it to have increase surveillance capabilities
+
+
Krausus updated:
+
+
Karma spending is now slightly more straightforward and sanity-checked.
+
Ghosts can now see non-crew antagonists in the Award Karma listing.
+
You can now ctrl+click on yourself to stop pulling something.
+
+
Kyep updated:
+
+
Added Syndicate Infiltration Teams (SITs), which are like Syndicate Strike Teams (SSTs) but focusing on stealth rather than direct combat. Useful for getting ghosts into rounds, spicing up rounds, having traitors with teamwork, and new kinds of traitor objectives like kidnap.
+
Fixed bug that Dust implants had no icon.
+
+
LittleBigKid2000 updated:
+
+
The arrivals checkpoint camera monitor is now connected to some camera networks by default.
+
Talking swords can now be understood by their wielders, and everyone else.
+
Engineering cyborgs now have floor painters. Absolutely nothing bad can happen because of this.
+
+
Norgad updated:
+
+
Coated Reinforced Walls now have unique sprites
+
+
TullyBurnalot updated:
+
+
Trash Bags fit in satchels/bags/duffelbags, but cannot be transported after being filled up.
+
Advanced Mops clean faster, can clean more
+
Holosign Projectors can create more signs
+
Ghosts can no longer create dirt
+
Dirt creation slowed down. "Clean Station" may actually be remotely possible now
+
Janitorial Closet tidied up
+
Can fill Light Replacers with boxes directly
+
Can recycle 3 broken/burnt bulbs into a functioning one
+
Can no longer cheat around NODROP by inserting NODROP lightbulbs into Light Replacers
+
Ghosts can no longer trip Proximity Sensors
+
Ghosts can no longer trip Infrared Sensors
+
Effects (like hallucinations) can no longer trip Proximity and Infrared Sensors
+
IDs are no longer dropped if their owner cryos with the ID inside a PDA inside a bag (very specific, yes)
+
+
Ty-Omaha updated:
+
+
Allows sechailer phrases to be selectable
+
Quick-equipping a PDA will now prioritize the PDA slot before the ID slot.
+
+
taukausanake updated:
+
+
Gives proper mix_messages for Uplink, Synthignon, and Synth 'n Soda drinks
+
+
tristan1333 updated:
+
+
Spacepod paint
+
+
+
08 August 2016
+
Ar3nn updated:
+
+
Telekinesis no longer is subject to meatspace problems
+
+
Chakirski updated:
+
+
Added animal AI holograms.
+
.45 Magazine sprites for the M1911 are now longer invisible.
+
Hoodies no longer look like labcoats while in hand.
+
Ectoplasm spawns in cult mining rooms instead of an invisible "weapon".
+
Duffel bag descriptions and names no longer contain "duffle".
+
Syndicate medical duffel bags can now be seen while in hand.
+
+
Crazylemon64 updated:
+
+
Adds a "Save" buildmode for admins to preserve their creations for later. This is currently in an early stage, so don't be surprised by errors!
+
+
FlattestGuitar updated:
+
+
Holy Water will no longer make you stutter for ages if you're not a cultist
+
+
Fox McCloud updated:
+
+
Fixes Orion Ship message being unheard when held in-hand
+
Adds headphones into the game as a loadout item
+
Removes fireproof core malf AI power
+
upgrade turrets malf AI power CPU reduced from 50 to to 30
+
Overload machine cost increased from 15 to 20
+
Override machine cost increased from 15 to 30
+
can override/overload field generators again
+
Machine uprisers will slowly die if they aren't attacking someone
+
Adds in Hostile lockdown malf AI power for 30 CPU
+
Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively
+
AI's no longer have flood mode on air alarms by default
+
Adds in lip reading malf AI power for 30 CPU
+
Allows accessories to hypothetically grant armor to their wearer
+
Greytide spear illusions actually have an attack sound now
+
fixes the wormhole event being much shorter than intended
+
+
FreeStylaLT updated:
+
+
Walls now melt when hot
+
Added actual coated rwalls - you can make them by clicking on an existing rwall with at least 2 plasteel in hand. Has infinite temp resistance.
+
Replaced all fake coated rwalls with new rwalls in both metastation (where they should be) and boxstation
+
Bandaging someone no longer stabs your eyes with bright green
+
Fixed repainted-to-wood metal flooring in courtroom - it's now actually wood
+
Fixed windoor in witness stand facing the wrong way
+
+
KasparoVy updated:
+
+
Traitors with the Maroon objective will no longer succeed if their target is in a locker on the shuttle.
+
Traitors with the Assassination objective will no longer fail if their target is assassinated/borged/debrained but on a Z-level greater than the derelict.
+
+
Krausus updated:
+
+
Fire will now totally consume you, rather than timidly hiding under your clothes.
+
Admin freeze overlays should no longer disappear from humans until they're actually unfrozen.
+
+
LittleBigKid2000 updated:
+
+
Adds cheap sunglasses. They provide no flash protection, but are available in the loadout and clothesmate.
+
+
Pinatacolada updated:
+
+
Makes the swedish gene spit out weird swedish chars and sounds
+
+
Ty-Omaha updated:
+
+
Fixes "is too cumbersome to carry in one hand" from showing up to other players.
+
+
Yurivw updated:
+
+
Condimaster now actually makes bottles. Removed: Unused options in admin secret menu are now removed.
+
+
chopchop1614 updated:
+
+
fix bluespace crystals exploit
+
+
+
03 August 2016
+
Fox McCloud updated:
+
+
Fixes a rare case where the singularity would escape containment when properly set up+contained
+
+
Krausus updated:
+
+
Non-respawnable ghosts will no longer qualify for mid-round rejoining (event antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this.
+
Cryodorms will no longer produce respawnable ghosts for the first 30 minutes of the round.
+
Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above their cryo pod, in the spooky cryodorms.
+
Cryodorms will now despawn you 90% faster if you willingly enter one.
+
Suiciding in the first 30 minutes of a round will no longer allow you to ghost and be respawnable.
+
Becoming a non-respawnable ghost lasts the entire round, even if you ghost in a respawnable manner later on.
+
You can no longer spam pinging posibrains, and cannot ping them at all if you cannot volunteer for one.
+
Missing limbs will now be grayed out on your health doll.
+
+
chopchop1614 updated:
+
+
Fixed the C4 labcoat exploding bug
+
+
+
01 August 2016
+
Crazylemon64 updated:
+
+
Admins are now able to print a map of the z levels.
+
Admins are now capable of scrambling the z levels' transitions.
+
Janiborg trash bags no longer fit down disposals when empty
+
+
Fethas updated:
+
+
(Maybe?)..We actually check if the race HAS BLOOD before trying to suck them
+
Due to various complaints from tajarans having hand cramps, glove makers have removed plasteel from the fabric.
+
Plasmaman can no longer be vampires.
+
Removes the mask check on both victim AND vampire, also makes the message a bit more obscure, so it's up to your imagination of where you are biting them and with what.
+
+
Fox McCloud updated:
+
+
Medical stacks now have 6 uses
+
Medical stacks now heal 25 burn/brute
+
Applying a medical stack to others is instant, no matter what
+
Applying any medical stack to yourself has a 2 second delay
+
Applying a splint to yourself has a 10 second delay
+
No more RNG fumbling of putting splints to yourself
+
Confirmation for applying medical stacks is now green
+
Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, 1 roll of gauze, and medipen.
+
Amount of splints in medical vendors increased from 2 to 4
+
Fixes weird icon updates when getting healed by medical kits
+
Adds in object burning system that allows things to be lit on fire
+
being on fire should heat you up a bit quicker and do a bit more damage
+
Novaflowers ignite you rather than uselessly heating you up
+
Adjusts a few pyrotechnic chems to better fit with other tweaks to fire damage
+
+
IcyV updated:
+
+
Adds a unique axe for Atmos-traitors
+
+
Krausus updated:
+
+
Probably fixed some very specific items messing up View Variables for no adequately explicable reason.
+
Fixed round-end antagonist report failing to print due to null objectives.
+
+
Kyep updated:
+
+
Added atmos grenade kit to traitor uplink.
+
Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes #5232
+
+
TheBeoni updated:
+
+
Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security one Added picture because i do not like that red label
+
+
TheDZD updated:
+
+
Shadowling ascendance and badmins pressing the "Destroy All Lights" button should no longer bring the server to its knees.
+
Broken lights will no longer re-break.
+
+
TullyBurnalot updated:
+
+
Using ATMs leaves fingerprints behind
+
+
Twinmold updated:
+
+
Nuke Ops airtank connected to pipenet now.
+
+
tigercat2000 updated:
+
+
Readded colored cable-cuffs.
+
Making stacks of metal rods now updates the icon correctly.
+
+
+
28 July 2016
+
A Giant-Ass Mountain of Salt updated:
+
+
Re-adds PDA slot.
+
+
Crazylemon64 updated:
+
+
Adds an explosion buildmode
+
"Drop Everything" in VV no longer causes limbs to fall to the ground.
+
+
FlattestGuitar updated:
+
+
IAAs can now select the classic secHUD in loadouts
+
adds bananas and suit jackets to the loadout system
+
adds dress shoes and fancy sandals to the loadout system
+
Miners can now get the mining coat from loadouts
+
+
Fox McCloud updated:
+
+
Fixes organ repair surgery saying an organ wasn't damaged when it actually was
+
Removes the 1 burn heal from regular ointment
+
Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)
+
Fixes a few crafting recipes not having the proper category
+
Fixes laser slugs not firing lasers
+
Adjusts the damage/consistency of improvised slugs
+
Adds in craftable bolas; throw them at someone to slow them down
+
Secvend starts off with e-bolas
+
Can make spears with personal crafting now
+
Fixes teacups and some other drinks having no sprite, in-hand, or object
+
adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies
+
Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand
+
Fixes cablecuffs not having a unique in-hand icon
+
Fixes cable coils not having a unique in-hand icon
+
All cablecuffs will be red, regardless of what they're produced from
+
Fixes an unlimited metal exploit
+
IV Drip sprites updated; has visual feedback for if it's injecting or taking blood
+
IV Drip injection rate dramatically increased
+
Warning ping for when someone is low on blood
+
Support for species with exotic blood type
+
Alt-Click to toggle between modes
+
Sensory restoration virology symptom no longer has anti-stun properties nor heals brain damage, but has a lower acquisition level
+
Damage convert heals individual limbs instead of healing overall damage (actual impact is low)
+
Librarian now starts off with a bookbag
+
Bookbag can now hold Bibles, cult tomes, books, and spellbooks
+
Can empty a bookbag into a bookshelf
+
Fixes an exploit where you could generate wood out of thin air
+
Fixes blobspores doing more damage than intended
+
+
Fox-McCloud updated:
+
+
Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws
+
Fixes some personal crafting behaving as other than intended
+
+
FreeStylaLT updated:
+
+
Fixed brig cell block APCs not getting power
+
Fixed space buggery Kyet made :angry:
+
Fixed missing light near labor shuttle dock
+
Fixed wrongly placed cobweb in solitary
+
Fixed basketball court not having a basketball
+
Added windows to brig processing entrance
+
Re-added the missing EOD and biohazard lockers in Armory
+
6 gas masks from Armory
+
Added grid check into random events.
+
+
Krausus updated:
+
+
The voting panel now uses the browser datum, which means it looks nicer.
+
The voting panel now updates while a vote is in progress.
+
When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in "vote".
+
Custom votes will now show full voting results upon completion.
+
Admins should no longer lose the "cancel vote" link in the voting panel.
+
View Variables should probably stop crashing admins.
+
The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen.
+
Admins now have click shortcuts for opening a player panel, showing mob info, and viewing variables. Specifics are in Hotkey Help.
+
+
Kyep updated:
+
+
Admins can now see attacks against SSD players more easily.
+
Clarified the text you get when examining a SSD player.
+
It is now possible for admins to remove a person's vamp thrall status.
Removes space parallax, due to server overhead, input lag & bugs
+
+
+
21 July 2016
+
Alffd updated:
+
+
Added a 6th Vulpkanin tail option.
+
Fixes animations, side view, and pixel fill for Vulpkanin tail 6
+
+
FalseIncarnate updated:
+
+
Engineers can properly show up for work with their hats and coats to keep warm.
+
+
Fox McCloud updated:
+
+
Tajarans and Unathi can now wear all shoe and glove types
+
Glove clipping removed except for black gloves, which makes them fingerless gloves
+
Adds sandals as a loadout option
+
Adds in simple animal mob spawners
+
Adds shielded hardsuit to the nuke ops uplink for 30 TC
+
Implements the powerfist and adds it to the uplink for 8 TC
+
Removed drinking glass shattering (regular bottle shattering is still a thing)
+
Captain's flask is now gold instead of silver
+
Bottles have a throwforce of 15
+
can crack eggs into drinking glasses
+
Detective's flask starts out with 30 units of whiskey
+
removes redundant object verbs that have an action button
+
Fixes up mindswap spell so it behaves more properly
+
Fixes genetic abilities action buttons not properly clearing
+
Fixes simple animals, silicons, and brains becoming perma deaf from flashbangs and other sources
+
ACTUALLY FIXES MINING APC
+
Fixes brig cell timers not having the option to flash people
+
+
FreeStylaLT updated:
+
+
Added new syndicate item Chameleon SecHUD to uplink store, available for all antags. It can morph into various eyewear while being a flashproof sechud.
+
+
Kyep updated:
+
+
Added new syndicate costumes to "select equipment" admin verb.
+
+
TullyBBurnalot updated:
+
+
More beds outside the Operating Theaters, Pajama Wardrobes outside and inside the Operating Theaters, an extra NanoMed Vendor, one Disposal Chute per OR, table with cards
+
Sinks moved closer to Surgical Tables, moved light fixtures in the Operating Theaters, tables with surgical tools now made of glass for maximum style points and Xenomorph Larva Whack-A-Mole
+
+
monster860 updated:
+
+
Brig timer UI reopening after being closed fixed.
+
+
+
20 July 2016
+
Allfd updated:
+
+
Added hologram fluff sprites
+
+
Ar3nn updated:
+
+
Gets rid of some weird lattices floating in mid-space
+
+
Chakirski updated:
+
+
Adds M.E. Reaper sprite.
+
AI can now choose a 32x64 reaper hologram.
+
Cigarette packs no longer show near-duplicate messages when examined.
+
+
CrAzYPiLoT updated:
+
+
Ports randomized space ruins from /tg/ station. There is a number of maps which can be spawned at any location on the empty z-level at roundstart, and up to three random ones will be chosen each round. Credits to KorPhaeron.
+
Lays the groundwork for a future lavaland implementation, if we choose to have it.
+
Adds a feature to the map loader where areas with the right var set can be distinctly initialized on map load - meaning separate APCs, and the like.
+
Using a z-level specific initialization freeze system, large elaborate maps like the cyberiad can be loaded without a single runtime, with minimal impact on the round elsewhere.
+
Adds a delete mode to the "Fill" buildmode - just alt-click for the second corner, and everything within will be removed.
+
Adds a "Jump To" function in VV, which is useful for getting an idea of what exactly you're looking at.
+
Added view count to newscaster feeds and messages.
+
+
Crazylemon64 updated:
+
+
Abductors consoles link correctly again
+
+
DaveTheHeadcrab updated:
+
+
Plastic explosives are now a subtype of grenades. Shouldn't be any noticable difference for players.
+
Plastic explosives no longer use the wire datum. You may directly attach an assembly holder (Such as a remote signaller + igniter assembly)
+
Adds X-4 shaped charges, designed for breaching explosively without harming the user. Pick some up at your local nukies r us.
+
Replaces tablecrafting with personal crafting, click the hammer icon by your intent selector to use it.
+
Removes the PDA slot, your PDA can now go in your ID slot (Again).
+
You can now alt click to remove an ID from a PDA, for quick interaction while it's in your ID slot.
+
Adds an overlay for an ID while it's inserted into your PDA.
+
+
FalseIncarnate updated:
+
+
Adds new Bottler machine for making unique beverages! Order one from cargo today!
+
Adds 6 new drinks obtainable via the Bottler. Get brewing!
+
Grapes now can be properly juiced again, as they now have the right kitchen tag.
+
Adds effects to the Paradise Pop reagents. Drink them all to unlock their powers!
+
+
Fox McCloud updated:
+
+
Adds in fans which can block atmospherics passing over them
+
All mass driver blast doors have a fan underneath them, allowing you to use them repeatedly instead of once
+
Fixes medical, security, and employment records not being displayed
+
Adds in a weather system
+
Removes most of the miner's uniform equipment from their lockers and puts it in a miner's wardrobe
+
Miners start off with a lot of their clothing equipment equipped to them
+
Miners now have unique headset sprites
+
Miners no longer have lanterns, but a seclite; they can attach this to their kinetic accelerators now
+
Miners have workboots instead of black shoes
+
Miners no longer have a default mining scanner but an advanced one that works at reduced range (5 instead of 7) and has a longer cooldown between pulses (5 instead of 3.5)
+
removed extra mining hardsuit from the outpost
+
removed medikit spam from outpost; now just a toxin kit and a regular medical kit
+
Bluespace crystals now earn you points and can be refined into bluespace polycrystal sheets
+
Spare vouchers from QM and HoP removed
+
removed armor from the fake tactical turtleneck
+
Can scan vending machines with your PDA to pay for items (if there's an ID in your PDA)
+
Sleepers no longer require a console to build, only the sleeper itself
+
Clicking on the sleeper brings up the menu that was previously brought up for the console
+
Adds in syndicate sleepers--these sleepers are not only syndie themed but also allow the user to inject chems into themselves while inside the sleepers
+
Sleepers can now inject silver sulfadiazine
+
removes cryofeeds from cryodorms and adds in 2 more cryopods
+
Fixes pre-spawned loaded belts not having proper overlays
+
nanites will no longer purge chems, but will now heal internal organ damage, attempt to mend fractures, and will no longer cure beneficial viruses
+
cold and hot drinks should now properly heat you up or cool you down (this also goes for medical reagents)
+
beer no longer reduces jitteriness
+
toxins special and antifreeze heat you up
+
banana juice and banana honk now heals monkeys
+
Fixes atrazine not killing nymphs
+
mining autoinjectors no longer poison you
+
combat hypospray now has omni+epinephrine+teporone
+
stimpack is now meth+coffee instead of meth+epinephrine
+
Cheese and synth meat amount creation scales with volume of the reaction
+
sprinkles now heals all members of sec (brig phys, sec pod pilot, magistrate, and IAA are no longer left out)
+
Fixes syndi+shielded+hos hardsuit sprite issues
+
Fixes wizard's who have a regular satchel set in their prefs winding up with none
+
Spellbooks are automatically bound to wizards at round start (no more ragin' exploitative mages)
+
Fixes mining outpost lacking an APC
+
Fixes being able to exploit and turn artificial bluespace crystals into regular bluespace crystals
+
+
FreeStylaLT updated:
+
+
Added courtroom, left of brig.
+
Remapped brig
+
Moved prisoner processing and evidence storage to the right of brig, next to Detective's office.
+
Changed current processing to Interrogation and a hallway.
+
Re-mapped Conference and Locker rooms.
+
Lots of other minor tweaks to brig.
+
Seriously, way too many small changes to list here, go and have a look at the brig yourself.
+
Removed temp. detainment and observation from brig.
+
+
KasparoVy updated:
+
+
Wearing a suit will no longer cause runtimes due to the way suit-collars are handled.
+
The north direction sprite of the Vulpkanin 'Patch' facial hair style won't hang a pixel off the head anymore.
+
+
Krausus updated:
+
+
All admins can now see "admin log" messages.
+
Admins can now toggle "admin log" messages on or off.
+
Admins will no longer be notified about ghosted admins jumping around.
+
Beating on simple animals will no longer be twice as noisy as intended.
+
Emergency Response Teams are now usable again.
+
+
Kyep updated:
+
+
adds botany, basketball court, individual cells, library computer and more to perma. Makes it far less boring.
+
Tracking implants are now useful, showing the implanted person's general location, and health status, on prisoner consoles.
+
The NODROP flag now works correctly on jumpsuits.
+
Improved admin 'select equipment' verb. ERT option now works, costumes get IDs and proper headsets, two new costumes added, and some outfits minorly tweaked (e.g: tunnel clowns get toolbelts).
+
Prevented NPCs being made into objective targets.
+
+
LittleBigKid2000 and TullyBBurnalot updated:
+
+
Stethoscopes can now be used to tell if a person's heart or lungs are damaged, or if they have any at all. Now they're actually useful instead of telling you the obvious in a vague way.
+
Stethoscopes can no longer be used to hear the heartbeat and breathing of a person that doesn't have a heart or lungs.
+
+
Tauka Usanake updated:
+
+
Adds a Hydroponics HUD and a night vision version of it that can both be created in R&D. It provides additional details on plants in hydro trays and soil plots. Shows the health, nutrient, water, toxin, pest, and weed level of the plant as well as whenever it is ready to be harvested or is dead.
+
+
TullyBBurnalot updated:
+
+
Handless cuffing no longer possible. Can still cuff people with one hand
+
+
TullyBurnalot updated:
+
+
Mobs with PSY_RESISTANCE are no longer valid targets for REMOTE_VIEW
+
When emagged, Photocopiers now have a cooldown if used to copy butts
+
+
Twinmold updated:
+
+
Fixes removing ID cards from laptops with the Eject ID verb.
+
+
monster860 updated:
+
+
A bunch of interfaces now use /datum/browser.
+
The ChemMaster now uses the asset cache, eliminating the enormous lag spike when you first use it. Yey!
+
Fixes the window not closing when selecting an icon for the chem-master
+
Fixes the chem master window not updating when selecting an icon
+
The chem-master icon selection window now has a 4x5 grid of icons.
+
+
tigercat2000 updated:
+
+
Gas tanks now have an action button for accessing their interface.
+
You can now shift-click on movable HUD elements (such as action buttons) to reset them to their initial position.
+
Implants with limited uses, such as freedom implants, now delete themselves when they run out of uses.
+
+
+
13 July 2016
+
Ar3nn updated:
+
+
Adds a silence button to newscasters, which will silence the regular update sounds
+
+
Chakirski updated:
+
+
Adds new bacon sprites.
+
Bacon can now be cooked from the grill. Just grill raw bacon.
+
Raw cutlets are now sliceable into raw bacon strips.
+
Plasma and N20 look more gassy.
+
+
DaveTheHeadcrab updated:
+
+
Greys no longer speak in wingdings.
+
Greys now have a species-specific language.
+
+
Fox McCloud updated:
+
+
Overall borg power useage has been lowered
+
Borgs who have completely run out of power can now still move around/see/talk, but they will be unable to interact with machinery/doors around them; they can still bump open doors, however. Borgs with no cell are still completely paralyzed and can't do anything.
+
IPCs are now properly impacted by space's burn damage
+
NT Rep's cane stuns for less and invokes a cooldown between use, similar to telebatons
+
Oxygen damage number changed a bit; damage is based upon volume lost more now
+
Species that have blood but are oxygen immune will now take tox damage
+
Health analyzers will now work with species with exotic blood and inform the user what type of exotic blood they have
+
Other machinery that display blood levels (op table, sleepers, advanced scanners, etc) will now work with exotic blood
+
Changeling regen will now properly restore blood if you have exotic blood fix Fixes being blurry for 20+ minutes when you were low on blood for a mere 3 minutes
+
Heart damage impacting blood volume removed
+
Nutrition draining when low on blood removed
+
Station cinematics shouldn't have inventory overlays over top of the animation
+
Station cinematics should properly clear off the screen and delete now
+
pAIs are no longer valid targets for gun turrets (like on the syndicate ship)
+
Adds in Rathen's secret, a new spell for the wizard that AoE stuns
+
Removed borg jetpacks
+
Adds in borg ion pulse system; borgs with ion pulse enabled consume extra power for each turf they move but can travel on space. Can upgrade any borg, at R&D with an ion pulse upgrade
+
Adds in cyborg self repair upgrade: very slowly repairs cyborgs at the cost of extra power. Available at R&D
+
Mining cyborg module tweaked slightly: GPS, shovel, mini welding tool and mini extinguisher added, wrench and screwdriver removed
+
reset borg module removes speed boost
+
Fixes borg's stun arm bypassing shields
+
+
KasparoVy updated:
+
+
Adds Vox compatible versions of all jumpskirts.
+
Adds Vox compatible version of the CMO jumpsuit.
+
+
Krausus updated:
+
+
Players will ALMOST DEFINITELY never get stuck as plants anymore. I mean it this time!
+
Fixed morgue trays not updating themselves when you ghost into/out of your body.
+
+
Kyep updated:
+
+
Changed access requirement on lethal injection locker to sec access (same access required for the chair its right next to.
+
Changed access requirement on exile implant locker to armory access.
+
Ghosts no longer miss out on ERTs due to not knowing it was called, or not being able to find the verb. They are now prompted about joining an ERT when one is called.
+
Fixed a condition where 'we are assembling an ERT' message is broadcast, but no ERT is generated.
+
Typo fixes in ERT messages.
+
Entering a cryo pod, then deliberately selecting OOC->Ghost, and clicking yes on the prompt, will now instantly send you to long-term storage, removing you from the round, despawning your body, freeing your job slot, and giving a new objective to any antag that had you as a target.
+
Announcements about someone entering long-term storage via a cryopod now include that person's rank.
+
When an antag target cryos, the message the antag gets about their objectives changing is now clearer.
+
+
TheDZD updated:
+
+
Adds "salts" as a say verb for deadchat ghosts.
+
+
TullyBurnalot updated:
+
+
Universal Recorder added to NT Rep Locker
+
Box of recorder tapes added to NT Rep and IAA Locker
+
Fax Guide added to Captain, HoS, HoP, NT Rep and IAA Lockers
+
Butt copy alert added to photocopiers
+
Butt copy alert comes with *ping noise
+
Photocopiers start with 60 toner
+
+
Twinmold updated:
+
+
Vampires with sleeping carp (traitor+vampire rounds) can now suck people's blood like normal.
+
+
monster860 updated:
+
+
The ChemMaster now uses NanoUI! Yey!
+
Alerts are no broken ghostly outlines
+
+
+
09 July 2016
+
Chakirski updated:
+
+
Adds disabled_component() to cyborgs.
+
EMPs now disable binary communication for as long as the stun time.
+
Syndicate thermal imaging glasses (mesons) can now be prescription upgraded like normal mesons.
+
Green glasses from the AutoDrobe can now be prescription upgraded.
+
+
FalseIncarnate updated:
+
+
Deepfryers are no longer arcane mysteries, and can be (de)constructed and upgraded.
+
+
Fox McCloud updated:
+
+
Grenade have a chance to explode when the person holding them is shot
+
Flamethrowers can release their tank's contents if the person holding them is shot
+
Can no longer self-trigger blocked shield events (ie: no self-harm to trigger a reactive teleport armor)
+
Hugging someone/shaking them up bypasses shield checks (oh no, hugs of death)
+
Riot shields have a +30% chance to block thrown projectiles
+
Hunter pounces are now a thrown attack as far as shield go, and yes, can be blocked by riot shields now
+
Energy shields no longer block anything other than beam and energy projectiles
+
Being able to be pushed is based on the block chance of the item you're holding instead of it just being based on riot shields
+
Adds in cursed wizard heart, purchase it from the wizard's spell book for 1 point, but be wary of not keeping the heart beating...
+
+
FreeStylaLT updated:
+
+
Added a bunch of new items to maint, some rare uplink gear included. (see PR for full list)
+
made gas masks, nothing and extinguishers less common in maint
+
+
Krausus updated:
+
+
Players probably won't get stuck as plants forever anymore. Probably.
+
Refactored job ban checking, which should massively reduce round start-up time.
+
Job bans/unbans will now take effect instantly, rather than at the next server restart.
+
+
TheDZD updated:
+
+
DNA injectors no longer always activate powers that are supposed to have a chance to activate.
+
Dionae can no longer activate the radiation disability, nor the run superpower except via adminbus.
+
Adds genetic instability, which causes a variety of negative effects, including toxin damage, burn damage, cloneloss, and even gibbing. Effects get worse as stability gets lower, burn damage starts below 85 stability, tox and clone below 70, and gibbing once you're below 40.
+
Adds Curse of the Cluwne touch attack spell, which wizards can pick, heavily based off of the same spell from Goonstation. Said spell adds an unremovable honk tumor to the target, gives them NODROP neon green clown gear, makes them stutter, makes them almost eternally fat, confuses them, makes them clumsy and speak in Comic Sans, and severely brain damages them. Use it on a cluwne however...
+
Fixes a bug where honk tumors would cause NODROP items to still be moved, despite being unable to be unequipped.
+
+
TullyBurnalot updated:
+
+
Botanist access to the morgue revoked
+
Added custom messages for evil faxes
+
Added unique text body for each non-evil fax template
+
Added a "Keep up the good work" fax template
+
Added a "ERT Instructions" fax template
+
Photocopiers can be emagged
+
Emagged photocopiers deal 30 burn damage to all mobs copying their butts
+
Deconstructing Comfy Chairs yields 2 metal sheets
+
Boxes no longer allowed inside evidence bags to prevent them going into themselves
+
Monocles are now prescription upgradable
+
Monocles added to Loadout selection
+
Spinning a revolver's chamber makes a noise again
+
Revenants can actually be killed now.
+
AntagHUD activation disqualifies player from rebooted drones
+
Sergeant Ian hat now visible
+
+
Twinmold updated:
+
+
Fixes the inconsistency of getting 2 metal rods when you wirecutter a destroyed grille down to 1.
+
+
+
07 July 2016
+
Ar3nn updated:
+
+
Adds tech levels to RnD console main menu
+
+
FalseIncarnate updated:
+
+
Chicks no longer lose their souls (literally) when becoming adults.
+
Intercoms, fire alarms, and air alarms no longer contain internal portals to a realm of infinite cables and circuit boards.
+
+
Fox McCloud updated:
+
+
Space lube damage removed and duration reduced from 7 to 5
+
Azide and CLF3+Firefighting foam now play a bang sound when mixed
+
Can now pet pAI's with help intent
+
Fixes sechuds and nightvision sechuds having flash protection
+
+
FreeStylaLT updated:
+
+
Added windows and a missing firelock to Genetics/Cloning
+
Tweaked layout of Genetics slightly
+
Added photocopier to R&D.
+
Tweaked RD's office layout slightly
+
Changed access on Tcomms' external airlocks' buttons to be same as general Tcomms access
+
fixed the airless tiles in Assembly Line's windows
+
+
KasparoVy updated:
+
+
Adds improved Vox mask/goggle sprites.
+
Adds Vox-compatible versions of most suits.
+
Adds species-fitting and icon override handling to clothing accessories and suit collars.
+
You can now open/close Clown Officer and Soldier coats.
+
Adds by-species tail hiding.
+
Tidies up and refactors the way the Captain's space helmet shows Vox hair but hides every other species'.
+
Reactive armour's sprite will now update as soon as you turn it on/off or EMP it.
+
+
Krausus updated:
+
+
Fixed borers dying in hosts who happened to be somewhere cold, such as space. Even if their host was in a space suit.
+
Fixed borers forgetting to detach from a host when it died.
+
Fixed borers being able to assume control of a dead host.
+
Fixed dead borers in a host being able to speak with the host and ghosts.
+
Fixed employees starting every shift at least 3 minutes late. You aren't getting paid to stand around, people!
+
Fixed animal beatdowns being twice as noisy as they should be.
+
Pod lock busters should now properly bust pod locks.
+
The late-stage effects of the "sensory destruction" disease symptom should now properly destroy your senses.
+
Autotraitor should now continue picking new in-game traitors, instead of picking one and dying.
+
Lacking a head no longer makes you immune to becoming a husk or skeleton.
+
Security and medical records should probably stop crashing people.
+
Altering details on an Agent ID Card will now actually update what's seen when examining the card.
+
+
Kyep updated:
+
+
Fixes NT Special Ops Officer's headset so he can correctly hear, and talk on, the Special Ops (deathsquad) channel.
+
Fixed oversight in keycard authentication devices that incorrectly treated trialmins like fullmins, resulting in situations where calling an ERT became impossible.
+
If an ERT request gets no answer for 5 minutes, admins now get a one time reminder that it was sent.
+
+
TheDZD updated:
+
+
Burst fire selection is now a proc, as it was meant to be, rather than a verb.
+
+
TullyBurnalot updated:
+
+
AI can no longer interact with IV Drips
+
Robots can no longer remove beakers/blood bags from IV Drips
+
Fixed clown door deconstruction
+
Fixed mime door deconstruction
+
+
+
02 July 2016
+
Fethas updated:
+
+
adds comfirmation dialogs to transforms from player panel
+
+
Fox McCloud updated:
+
+
Adds in laughter demons
+
Can summon laughter demons as a wizard
+
Chem master can produce instantaneous medical patches if all chems are safe
+
Can now purchase sniper rifle and associated ammo on uplink during nuke ops
+
Most melee and laser armor values halved or reduced; some bullet armor reduced slightly
+
Slowdown on most armor and spacesuits reduced by 1 (chaplain armor is still slow though)
+
Mining armor caps out at 60 melee resist as opposed to 80
+
Ling melee armor reduced; bullet and laser values buffed a bit and slowdown removed
+
Chameleon jumpsuit has a little bit of armor
+
Detective's forensic jacket now has identical armor to the native detective jacket
+
Armor penetration added to energy swords, chainsaws, scythes, and spears
+
Fixes stun batons, telebatons, and abductor batons piercing/bypassing shields
+
+
FreeStylaLT updated:
+
+
Adds appropriate battle yells to sleeping carp
+
+
KasparoVy updated:
+
+
Engineer boots that've had their toes cut open now have a sprite.
+
Vox now have engineer workboot sprites.
+
Removes unused SWAT boot sprites that were really just copypasted jackboot sprites.
+
+
Krausus updated:
+
+
The late-join job listing is now big enough to show all the jobs at once, and organizes them into labeled categories.
+
Fixed Hotkey Help and hotkey mode toggle messages not appearing.
+
The late-join job listing will now ignore (mis)clicks for the first second after popping up.
+
+
Kyep updated:
+
+
"Loyalty" implants are now known as "Mindshield" implants
+
Admins playing CC jobs can no longer get antag status from autotraitor.
+
+
Tastyfish updated:
+
+
There's essentially a completely new space hotel map! Explorers rejoice!
+
+
TheDZD updated:
+
+
Chance for vampires to burn in the chapel has been greatly reduced (from a 35% chance down to 8% per tick).
+
Vampires do not scream from chapel/space burning until they actually start catching fire.
+
Threshold for vampires to catch fire from space/chapel burning changed from 60 health to 50 health.
+
Fire stacks from vampire burning no longer apply twice 35% of the time while below the health threshold.
+
+
VampyrBytes updated:
+
+
No more *me emoting from your corpse!
+
+
monster860 updated:
+
+
Fixes ghosts having a generic icon when darkness is toggled off
+
+
tigercat2000 updated:
+
+
There's a new tab in the character setup screen, "loadouts". This allows you to spawn with a limited number of preset items.
+
Character setup now uses #defines for the different tabs.
+
+
+
28 June 2016
+
CrAzYPiLoT updated:
+
+
Replaced the current recycler sound with a new one.
+
+
DaveTheHeadcrab updated:
+
+
Adds workboots to be worn by engineers.
+
Fixes the scanner's search functionality.
+
+
FalseIncarnate updated:
+
+
To save on adhesive costs, Nanotrasen has stopped gluing stools to the floor. The resulting bodily injuries probably won't cost more than the glue.
+
+
Fethas updated:
+
+
you can now pick up potted plants and stealth
+
+
FlattestGuitar updated:
+
+
changes some alcohol values, the weaker ones are no longer as weak
+
refactored alcohol, you can now take short breaks between sips and still pass out in a gentlemanly manner
+
different species have different levels of alcohol resistance, check in with your bartender for more information
+
The medical HUD will now be a bit smoother. Neat.
+
+
Fox McCloud updated:
+
+
Warden starts off with a pair of Krav Maga Gloves
+
New Steal objective: steal the warden's krav maga gloves
+
Clonepods will automatically suck in nearby meat
+
Slime processors will automatically suck in nearby dead slimes
+
Actually fixes vamp chaplains
+
Fixes clumsy check on guns not working properly, resulting in people with glasses shooting themselves in the foot
+
pAI candidates can now see who requested them
+
+
KasparoVy updated:
+
+
Adds Yi to Vox-pidgin syllables. (Port from VG.)
+
Adds framework for icon-based skin tones. (Port from VG.)
+
Adds Vox-compatibility for all remaining eyewear.
+
Raiders now get a random skin tone and eye colour on spawn.
+
Species default hair, facial hair and head-accessory colours can now be defined.
+
Newly created Vox mobs will spawn with the same hair colour as they used to have pre-greyscaling.
+
Noir vision will no longer grey out the HUD. (Port from VG.)
+
Tails will not be coloured if the person's species doesn't have skin colour.
+
Vox hair (head and facial) have been greyscaled and can now be customized by the full colour range.
+
IPC parts from the mech fabricator won't turn IPCs invisible upon attachment anymore.
+
+
Krausus updated:
+
+
Added a custom runtime error handler.
+
Added an in-game runtime viewer.
+
+
Kyep updated:
+
+
Admins now hear boink sound when faxed, command sends ERT request, etc
+
Admins can reply to faxes via radio
+
Admins can reply to faxes with pre-written fax templates
+
Admins can reply to faxes with 'evil faxes', special faxes that have negative effects on their intended recipient (and nobody else)
+
Admins can now join as "Nanotrasen Navy Officer", and "Special Operations Officer". They spawn on adminstation and ERT office, respectively. They are not announced and do not appear on crew manifest.
+
"Select equipment" verb outfits tweaked for consistency with the above job outfits
+
Teleporter on admin station now works.
+
Added antag-only warning to bee briefcase, to reduce chances of traitors killing themselves with it.
+
+
LittleBigKid2000 updated:
+
+
Space explorer corgis can now safely explore space
+
+
Norgad updated:
+
+
Maintenance around the incinerator has been expanded.
+
Engineering maintenance finally has an APC.
+
The incinerator has been moved eastward, there is now a construction area in it's previous location.
+
+
Tastyfish updated:
+
+
Cryo tubes, sleepers, and body scanners now eject random items the occupant dropped, upon the occupant being ejected.
+
+
TheDZD updated:
+
+
Adds an adminbuse gun that fires gun mimics, you can varedit the gun's `mimic_type` var to any gun path, and it'll fire that gun as mimics. By default it fires stetchkin pistol mimics.
+
Fixes minor issues caused by some guns having text paths for power cells.
+
Fixes some runtimes and inconsistencies with the telegun and temperature gun.
+
The Tesla engine has acquired a grudge for lockers, and will now smite any in its path.
+
Unstable bluespace teleportation devices have been removed from energy guns, meaning they should no longer teleport from one hand to another when switching firing modes.
+
+
Twinmold updated:
+
+
You can once again resist borer control with the Resist verb.
+
+
VampyrBytes updated:
+
+
Emotes can now be accessed through verbs as well as say *
+
Emotes accessed through say * no longer take parameters after a -
+
Emotes now take parameters through input boxes
+
Emotes now have support for blind and deaf characters
+
Emotes now personalise messages
+
Flip can now be targeted with or without a grab
+
All emotes that are affected by being muzzled now make the user make some kind of noise
+
monkeys now have access to all the emotes that the npc tries to perform
+
Leap genetics ability lets you jump over things
+
+
monster860 updated:
+
+
UI now gets it's own plane
+
RnD console now uses NanoUI! Sweet!
+
Fixes tranquillite being outside the box in the materials list. Mimes are supposed to be trapped inside a box, not outside one.
+
Replaces the weird unicode "x" character in some design names with the actual letter "x" so that it doesn't fuck up NanoUI
+
RCD gets a UI
+
RCD-built airlocks can now receive different types and accesses.
+
You can now shift-click to examine as silicon, instead of ctrl-shift-clicking, which is something absolutely no one would guess.
+
Pulsing multiple doors' "open door" wires at the same time using a remote signaller now actually opens them at the same time.
+
Fixes wormhole projector not having an icon.
+
Wormhole projector has 0 failchance now.
+
Portals made by wormhole projectors can be removed via a multitool
+
Fixes ghost being able to request docking at trader ship consoles
+
+
tigercat2000 updated:
+
+
Ported goon HTML chat from /vg/ / Goon
+
All uses of \black have been removed
+
All uses of \icon have been replaced with bicon()
+
+
tkdrg updated:
+
+
Admins now have a verb to wipe all scripts from telecomms.
+
+
+
19 June 2016
+
DaveTheHeadcrab updated:
+
+
Defibs now must be used within 3 minutes of death.
+
Combat defibs now induce heart attack when you stun with them (Emagged defibs have a 10^ chance to do this)
+
+
Fox McCloud updated:
+
+
Adds in the ability to make latex glove balloons (cable coil+latex glove)
+
Fixes latex gloves not having an in-hand icon for the left hand
+
Telephones will now ring when activated in-hand
+
Force on telephones removed
+
The break room privacy shutters now apply to all windows in the medical break room and not just the ones out front
+
His Grace grants massive stamina regeneration
+
pre-made styptic, silver sulfadiazine, and synth flesh patches now apply instantly
+
Styptic and Burn patches now have unique icons
+
Partially fixes graffiti so it's actually visible
+
+
FreeStylaLT updated:
+
+
changed its to it's in lockbox description
+
changed \red to formatting
+
changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to 1 TC
+
+
KasparoVy updated:
+
+
Secure briefcase now has the same flags, hitsounds, attack verbs, throw speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins now.
+
Dethralling a Shadowling thrall that has darksight activated clears their darksight.
+
+
LittleBigKid2000 updated:
+
+
The vox raider's base is now filled with nitrogen instead of regular dusty air.
+
+
TheDZD updated:
+
+
Teaches camera assemblies the meaning of the word "respect" (for NODROP items).
+
Sates the insatiable hunger that orange shoes once had for secborg cuffs.
+
Cryodorms will no longer kick you to lobby if you have logged off when they despawn your body, they will now always ghost you.
+
The defense values on the riot armor helmet is now identical to those on the riot armor suit.
+
Knight armor (including the chaplain's crusader armor) now has a slowdown of 1 instead of no slowdown.
+
+
Twinmold updated:
+
+
Fixes being able to eat cybernetic implants so you cannot eat them/force feed them to people.
+
Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability to insta-kill IPCs/incapacitate those with mechanical hearts.
+
Lowers amount of confusion given from Revenants from 50 to 20 per Defile.
+
Sets a maximum confused amount from the Revenant's Defile ability (now 30).
+
Makes Syndicate Bombs show a more accurate time remaining until detonation.
+
+
monster860 updated:
+
+
Makes stock parts build 5x faster
+
Adds a last-second loop-back sort pipe so that items with a mail tag don't end up on the disposals conveyer, and get flushed right back around. This enables an item to be sent from anywhere on the station to anywhere else on the station without going through the disposals conveyer.
+
Fixes a bug where drones can get stuck if they have their destination set to the RD office. This also fixes the bug where attempting to send a package from the test lab always ends up in the RD office.
+
+
tkdrg, Delimusca, Aranclanos, TheDZD updated:
+
+
Gun mimics (including wand, staff, projectile guns, and energy guns) created by the staff of animation will shoot things.
+
Mimics created by the staff of animation now have googly eyes.
+
Fixes the disturbing lack of death caused by wand of death projectiles.
+
+
+
12 June 2016
+
CrAzYPiLoT updated:
+
+
Fixed the long-lasting bug of handcuffed people keeping their chainsaws.
+
+
Crazylemon64 updated:
+
+
No more language message-spam on roundstart
+
+
DaveTheHeadcrab updated:
+
+
Adds a new icon for the detective's scanner.
+
Detectives scanner now has access to DNA and fingerprint records.
+
+
Fox McCloud updated:
+
+
Adds three new chaplain weapons: pirate saber, multiverse sword, and possessed/talking sword
+
Fixes not being able to sheath the claymore in the Crusader Armor
+
Adds in a mocha drink
+
Fixes ice being unobtainable for the jobs that use it most
+
Fixes laser armor losing its reflecting ability
+
Fixes the lack of progress bars for more stack-based construction
+
Fixes Experimentor producing coffee machines instead of cups
+
Can deconvert mindslaves by removing their mindslave implant
+
Can deconvert Vampire thralls by feeding them holy water
+
Fixes mindslaves not having a HUD for the master and mindslave
+
Fixes being able to duplicate just about anything in the Experimentor
+
Fixes not being able to use tank transfer valves or one tank bombs in the Experimentor.
+
Fixes infinite-throw spam
+
Fixes being able to resist out of grabs by moving (that is to say, it'll actually work now)
+
Fixes passive grabs using the wrong HUD icon
+
Tabling duration reduced from 5 to 2
+
Can no longer wield double-bladed energy swords as a hulk
+
Fixes on map stools having the wrong offsets, making it look like you're not sitting on them
+
+
FreeStylaLT updated:
+
+
Added (Enabled) Mind Batterer for Traitors
+
Fixed uplink implant description (Said 5 when actually gave you 10 TCs)
+
+
Glorken updated:
+
+
Shifts Zeng-Hu left leg over in order to regain thigh gap.
+
Chops off a pixel on Bishop feet so that they fit into shoes.
+
+
KasparoVy updated:
+
+
Old placeholder IPC butt sprite replaced with the finished QR-code sprite.
+
+
Krausus updated:
+
+
Fixes ghosts failing to follow mobs that move in unusual ways
+
Fixed tape allowing mobs with sufficient access to move through solid objects.
+
+
Many -tg-station Coders, TheDZD updated:
+
+
Old gun code is now gone.
+
Ports the vast majority of TG's gun code and their guns (any previously unavailable guns, and newly-added guns will remain unavailable to players). Expect some changes that might not be listed here due to the sheer scope of this refactor.
+
Probably some new bugs.
+
A lot of old gun bugs.
+
Mouth suiciding with a gun no longer instantly kills you, you fire the gun at yourself at 5x damage (assuming it even did damage to begin with).
+
Mouth suicide shooting does not work on harm intent.
+
You can now bash people with guns while on harm intent instead of shooting them point-blank.
+
You can now mouth suicide other people, doing so still takes the full 12 seconds to mouth suicide, but has the same 5x damage multiplier.
+
Vox spike throwers are real guns that fire spike bullets now, instead of just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor piercing, cause a 1 second stun (not the kind that drops you to the floor), and cause some bleeding. They have 2 round burst fire as well, and have 10 shots per clip. A new should should recharge every 20 or so seconds.
+
Xray lasers now have a maximum range of 15 tiles.
+
Zoomed guns now actually fire accurately while zoomed.
+
Using Suicide with guns now actually does gun-like things.
+
The clown no longer deletes guns if he fucks up with them due to being clumsy.
+
Emitters no longer become inaccurate over long ranges.
+
Power gloves now override middle-click and alt-click when worn.
+
Power gloves give a notification when worn.
+
Power gloves now have special examine text when examined by an antagonist.
+
Proto SMGs now only have a 21 shot clip.
+
+
Spacemanspark updated:
+
+
Adds the ability to make a more irritated buzz noise at people as a synthetic. The original buzz is still there.
+
+
Tauka Usanake updated:
+
+
Adds more belt icon overlays
+
+
Twinmold updated:
+
+
Nar'Sie AI Hologram and Error Sprite
+
Fixes space pod equipment variable. Can now properly install/uninstall equipment.
+
Check Seat verb no longer pulls out installed equipment.
+
You can now have a passenger in your pod if you have a passenger seat.
+
+
monster860 updated:
+
+
Adds comical implant. It is an implant that causes you to have a comic sans voice. It can be made in the protolathe using bananium.
+
The comical implant now spawns by default inside IPC clowns
+
Fixes the window getting stuck when you try to drag or resize a NanoUI window too fast with Fancy NanoUI enabled
+
Fixes a small quirk with the resize handle.
+
Fix javascript error in cargo UI
+
+
pinatacolada updated:
+
+
removes atmos tech SOP from supply SOP
+
Fixes defibing people without a heart
+
Fixes defib saying it didn't work stopping a heart attack when they do
+
+
+
02 June 2016
+
CrAzYPiLoT updated:
+
+
Fixed a text problem in virtual gameboard description.
+
Made gameboards deconstructable and movable.
+
Added a light to gameboards. Pretty!
+
+
Crazylemon64 updated:
+
+
There will no longer be a mountain of startup runtimes when people have custom languages.
+
+
DaveTheHeadcrab updated:
+
+
Removes xenobio golem rune creation sound
+
Added overlays for sec belts that reflect the items stored therein.
+
+
Fox McCloud updated:
+
+
Fixes Chapel and Chaplain's office not having a light switch
+
Fixes mass driver only being usable once due to weird pressure
+
Fixes chapel being overly dark near coffins
+
Fixes not being able to sheath the claymore in the Crusader Armor
+
+
IK3I updated:
+
+
crate cargo system
+
passenger seat system
+
loot box secondary cargo system (install it and your pod has a standard inventory)
+
lock busters for the CE and Armory
+
incappacitated people can't operate the door controls anymore
+
Items dropped in a pod can now be scrounged up
+
security can rip you out of an unlocked pod
+
The pod code isn't full of tumors any more
+
+
Tastyfish updated:
+
+
Holsters now have an action button while on your suit again.
Allows Chaplain to select a wide new range of null rod customizations
+
Slightly increases null rod damage (15->18)
+
Fixes abductors speaking other languages
+
Fixes traitors getting less TC on some game modes
+
+
QuinnAggeler updated:
+
+
All lazarus revived mobs become valid for pet collaring
+
+
Tastyfish updated:
+
+
Adds a suicide for light tubes.
+
Progress bars, buttons, and several of the values in UI's are now animated.
+
Deconstructing glass tables now gives a stack of 2 sheets of glass.
+
+
monster860 updated:
+
+
Upgrading the experimentor will no longer reduce the chance of upgrading an item's tech
+
Guest passes can now be attached to an ID card.
+
Adds a HoP guest pass computer, which is like a normal guest pass computer, but using an ID with ID computer access will allow it to issue guest passes with any access.
+
Adds the HoP guest pass computer to the HoP office.
+
Moves the guest pass computer in robotics to RnD.
+
+
+
25 May 2016
+
CrAzYPiLoT updated:
+
+
Adds an unread change notification.
+
+
Fox McCloud updated:
+
+
Removes Dragon's Breath Recipe
+
Removes Ghost Chilli Juice
+
Fixes buckled flipping over someone
+
+
IK3I updated:
+
+
Sleepers, scanners, and borg chargers no longer remove you from existence when destroyed
+
Hostile mobs are no longer fooled by your clever scanner and recharger tricks
+
+
+
24 May 2016
+
CrAzYPiLoT updated:
+
+
Adds the ability to attach signalers to bear traps. Stealthy hunting!
+
+
Crazylemon64 updated:
+
+
You can now fasten the circulators in the TEG kit with a wrench - no adminbus needed to set it up, now
+
You can now rename cassette tapes with a pen.
+
You can now wipe data from a tape from its right-click menu.
+
+
FalseIncarnate updated:
+
+
Adds 4 new types of fudge for the chef to make: Peanut, Chocolate Cherry, Cookies 'n' Cream, and Turtle Fudge.
+
Normal fudge recipe now uses milk instead of cream.
+
Mutant/Modified/Enhanced plants will no longer infinitely increase their name length, and instead will be simply "mutant", "modified", or "enhanced" plant as determined by the last type of modification they were subject to.
+
Bees can no longer phase through hydroponics lids, giving botanists a way to finally stem the tide of pollination.
+
Premade beeboxes now spawn with the right type of bees, specifically of the worker caste.
+
+
Fox McCloud updated:
+
+
Donk pockets have more omnizine, but only upon fully consuming the donk pocket
+
swarmers will drop an artificial bluespace crystal on death
+
Orion Trail guards now drop an energy shield and C20R on death
+
Reviving simple animals with strange reagent will prevent them from dropping any further loot
+
+
KasparoVy updated:
+
+
Rejuvenating a mob now unbuckles them correctly (if they're buckled to something).
+
Rejuvenating a mob will no longer remove their hair.
+
Rejuvenating a mob will no longer permanently blacken their eyes.
+
Rejuvenating a mob will no longer remove their prostheses with fleshy limbs, it will just fix the prostheses.
+
Rejuvenating a mob will not remove organs/limbs belonging to other species if said organs/limbs are in the same place(s) as the mob's default organs/limbs would be.
+
Fixes a runtime when trying to flip with an object other than a grab in your hand.
+
Doing a 'cybernetic repair' procedure on the head of a disfigured IPC will re-figure them.
+
Rejuvenating a mob will only regrow organs/limbs that are missing (by comparison to the standard organs for their species).
+
The regenerate_icons proc will now update skin tone and body accessories properly.
+
Organ rejuvenation now clears disfigurement and closes open wounds.
+
Rejuvenating a mob will end all in-progress surgeries.
+
Vox get their cortical stacks back, since the non-implant ones don't interfere with the Heist game-mode.
+
Rejuvenating a long-dead or husked mob will now clear the appropriate mutations.
+
+
QuinnAggeler updated:
+
+
Species disguise variable for clothing items
+
Species disguise string, "High-tech robot," for cardborg suit and helmet
+
ABSTRACT flagged clothing items will not be displayed on examination
Cryopods will now always display the occupant's name
+
+
KasparoVy updated:
+
+
Fixes a runtime with Dioneae by repathing their limbs.
+
+
QuinnAggeler updated:
+
+
Makes dehydrated space carp description more accurate and informative
+
+
monster860 updated:
+
+
Adds the permanent teleporter. Use the circuitboard on a teleporter hub to set the target before constructing it.
+
+
+
17 May 2016
+
AugRob updated:
+
+
Add screwdriver sound when opening/closing panels on airlocks
+
+
Fox MCCloud updated:
+
+
Removes "harm" traitor objective
+
Increases non-escape/hijack/die objectives from 1 to 2
+
Tweaks available objectives to traitors a bit
+
+
Fox McCloud updated:
+
+
Players can no longer see how many players have readied up or who has readied up
+
Hulks, Shadowlings, and Golems can no longer use laserpointers
+
Adds in the ability to flip over someone with *flip
+
Fixes and improves foam to better interact with reagents
+
+
KasparoVy updated:
+
+
Refactors hair so it's on the head (organ).
+
Adjusts some Vox hair style names so they're consistent with all others.
+
Refactors Morph and the order by which options are presented.
+
Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
+
Fixes some typos.
+
Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
+
Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
+
Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
+
Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
+
Adds a new Vox hairstyle.
+
You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
+
+
monster860 updated:
+
+
Fixes sleep() in telecomms
+
Windows can now be constructed and deconstructed using RCD's.
+
+
+
10 May 2016
+
Crazylemon64 updated:
+
+
Ragin' Mage creation works correctly again.
+
+
FalseIncarnate updated:
+
+
Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC)
+
Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees still murder them though)
+
+
FlattestGuitar updated:
+
+
Robots now slur and stutter robotically
+
Adds tape gags. Click on someone with a roll of tape to shut them up!
+
+
Fox McCloud updated:
+
+
Removes material efficiency upgrades from the mech fab and protolathe
+
Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down from 1 up to 4)
+
Fixes materials exploit duplication
+
Fixes the protolathe locking up under some circumstances
+
Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced.
+
removes fungus from mushrooms
+
adds fungus to "mold" plant
+
adds mold seeds to hydro vendor
+
bumps up ???? reagent from 1 to 5 on bad recipes
+
Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS
+
Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison bottles
+
Initropidril now has a recipe
+
Adds a number of new reagents
+
Brain burgers now contain prions instead of mannitol
+
Scientists and chemists can no longer purchase traitor poison bottles
+
random drug bottles now have a much wider range of reagents in them
+
Fixes UI On slot machine saying it costs 5 credits when it's 10
+
Fixes abductors having tails
+
Fixes traitor scissors having a different hair-cutting sound
+
Fixes simple animals not dying right away when they reach zero health
+
Fixes a few farm animals, simple xenos, and a hivebot from having incorrect health
+
Buffed health pack usage on simple animals (should heal roughly 20 damage on them, per use)
+
Emotes no longer need to be purely lowercase to work
+
Chaplain can now select a green book as his Bible
+
Adds in His Grace, a hijack-only traitor item for the Chaplain
+
+
IK3I updated:
+
+
Added key and tumbler based pod locks
+
Made Pod Locks and keys buildable in Pod Fabricator
+
Made Pod Keys recoverable from cryo
+
Added lock to Security Pod
+
Added a key for Security Pod to HoS and Pod Pilot Offices
+
New sprites for several pieces of pod equipment
+
Using a multitool on a decalock now gives usable info
+
+
NTSAM updated:
+
+
Fixes the stuttery rainbow screen for IPCs.
+
Fixes the green IPC screen.
+
+
QuinnAggeler updated:
+
+
Adds a sound emote for the Drask
+
Gives Drask the ability to eat soap
+
Adds a racial flag for the Drask
+
Makes syndicate, paramedic, clown, and EVA helmets display correctly on Drask
+
+
tigercat2000 updated:
+
+
The station blueprints can now show you where wires/pipes/disposal pipes are supposed to go.
+
+
+
04 May 2016
+
CrAzYPiLoT updated:
+
+
Adds gameboards to bar and permabrig.
+
+
Crazylemon64 updated:
+
+
AIs are no longer created for temporary messages.
+
+
Fethas updated:
+
+
Sniper Rifles for nuke ops.
+
you can now actually shove heads on spears again.
+
Before i removed the traitor chemist item i cleaned up the harm reaction code paths.
+
+
FlattestGuitar updated:
+
+
cheap lighters only damage your hand if you fail to properly use such a complicated contraption, not the whole body
+
ports /tg/ Foam Force guns, now you can shoot foam at your enemies /with style/
+
+
Fox McCloud updated:
+
+
Slime batteries now self-recharge.
+
Adds in door wands--control doors from range
+
Each head of staff (and the QM) starts off with a door wand to control the doors in their respective departments
+
Fixes nutrition alert icon kicking in too early
+
Adds in a new hairstyle
+
Fixes cig icons not updating under some circumstances
+
Updates the Tesla; it will now have to be "fed" or it can run out of energy; the rate at which it gains additional energy balls and power has been greatly lowered.
+
energy ball will now be drawn towards the singularity beacon
+
fuel tank explosions a bit stronger and will arc tesla blasts further
+
Tweaked some game mode population requirements to enhance general game mode balance and player experience.
+
Reworks overdosing to have more unique effects and also scale, in part, on volume
+
Epinephrine, Atropine, and Ephedrine have a lower OD threshold
+
Saline penetrates the skin
+
Synaptizine and Teporone now have OD threshold
+
Adds in berserker disease (treat with haloperidol)
+
Adds in Jenkem, a nasty gross drug made with toilet water
+
Adds in food poisoning; get it from eating poorly made food, from salmonella, or fungus
+
Adds in the Shock Revolver, a replacement for the stun revolver remove: removes the stun revolver remove: removes the prototype SMG+ammo from the protolathe
+
+
IK3I updated:
+
+
Can no longer holster items with No-Drop active.
+
Saves prosthesis users from Tox-Comp's wrath
+
+
KasparoVy updated:
+
+
Disembodied prosthetic heads that aren't monitors won't make you go bald when they're re-attached.
+
'Optic' markings will disappear when your head gets removed, and reappear if it gets re-attached.
+
Disembodied prosthetic heads that aren't monitors will now be rendered with hair & facial hair.
+
Disembodied prosthetic heads with optical markings (markings with the head set as the origin) will be rendered with those markings.
+
Animated hair styles (e.g. screens) and head accessories (e.g. 2/3 new antennae) will now be animated properly.
+
3 more antennae.
+
An alt. and monitor head model for every prosthetic brand but Zeng-hu. Morpheus only gets an alt model, not another monitor.
+
Animated optical markings to fit the new alt. heads.
+
Screen styles for the alt. Hesphiastos head.
+
Companies that make prosthetic body parts can (and do) now offer separate models for qualified recipients.
+
Removed the frames from screen styles in order to allow the same styles to be applied to all monitor heads.
+
+
LittleBigKid2000 updated:
+
+
Booze dispensers can now dispense synthanol
+
+
Norgad updated:
+
+
Adds a disposals chute to the Mechanic's Workshop
+
+
QuinnAggeler updated:
+
+
Adds the Drask as a 30KP race
+
Adds their language, Orluum
+
Adds a stylecolor for their language
+
Adds their butts (for photocopying)
+
Adds, at last, another race with skin tone (humies move over)
+
Adds a reason to make bad ice puns
+
Adds a check for brain death (brain damage of 120 or more) to the proc responsible for reviving IPCs
+
+
pinatacolada updated:
+
+
Makes fridge boards be selectable by screwdriving them
+
Virology fridge now accepts syringes, beakers, and bottles
+
Plasmamen security now spawn with their suit slot items in their bags
+
Pod pilots spawn with taser in the suit slot
+
removes armor from plasmamen magistrate suits
+
+
+
25 April 2016
+
CrAzYPiLoT updated:
+
+
Adds buildable holographic gameboards that, when opened, produce a fully-functional JavaScript chess interface, which includes a chess AI. If you win, it will produce 80 tickets for your spending!
+
+
FlattestGuitar updated:
+
+
a human's species is now visible on examination
+
+
Fox McCloud updated:
+
+
Improves attack animations with items, making it more clear who's attacking you and with what
+
Updates Revolution game mode so it better scales with total player population
+
Head revs start off with a flash, spraycan, and chameleon security HUD
+
Add chameleon security hud, which is basically sec shades with the ability to disguise as a number of regular glasses
+
Updates mining loot crates to feature far more actual loot
+
Mining loot crates are now opened by inputting a 4 digit password and have 10 tries to guess the password string
+
Fixes bees, mech syringes, and darts not properly calling INGEST for a reagent
+
+
Meisaka updated:
+
+
The light on/off function for drones works again, toggling between lowest setting and off.
+
Guardians can toggle their lights off and on again.
+
AI, pAI, robots and drones can now use *yes emote without extra ss on the end.
+
emote *help for silicons updated/added.
+
*twitch_s emote changed to *twitches, incorrect variations of some emotes can no longer be used.
+
+
tigercat2000 updated:
+
+
Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore"
+
You can now view HUD changes in real-time, by going to Preferences (top right tab) > Game Preferences and changing the HUD style (limited to humans).
+
There are now three HUD styles you can get via the f12 button- Full, which contains all of your buttons, Minimal, which only contains a few essential buttons, and None, which is a completely blank screen.
+
Removed the remaining aiming code due to maintainability issues and incompatibility with HUD styles.
+
Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if chain.
+
Refactored how objects (IE, stuff you pick up) is rendered to the HUD. This should fix the reoccuring "stuff on my screen that definately isn't meant to be there" bug, but keep an eye out for things that do not appear.
+
+
+
20 April 2016
+
Crazylemon64 updated:
+
+
Bureaucracy crates now contain granted and denied stamps.
+
+
FalseIncarnate updated:
+
+
Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code.
+
+
FlattestGuitar updated:
+
+
Adds shot glasses.
+
+
Fox McCloud updated:
+
+
Removes the ability to put a pAI into securitrons and ED-209's
+
Drinking glasses now have an in-hand sprite
+
DNA injectors no longer have a delay when used on yourself
+
DNA injectors no longer delete on use, but become used, much like auto-injectors
+
Fixes a bug where you can exploit the genetic scanner to get multiple injectors
+
Fixes not being able to cancel creating an DNA injector
+
remove spacesuits causing injections to the head to take longer
+
FIxes heat resist mutation not making you immune to high pressure, fire, or high temperatures
+
removes some not-well-known damage resists from cold/heat mutations
+
Re-maps botany a bit to make it more bee and botanist friendly
+
Adds in Abductors Game Mode
+
+
MarsM0nd updated:
+
+
Embeded object removal is now done with hemostat again
+
Borgs are able to do embeded object surgery
+
+
Tastyfish updated:
+
+
Makes the server startup substantially faster.
+
+
monster860 updated:
+
+
Crowbarring open a spesspod doors is no longer broken
+
+
tigercat2000 updated:
+
+
-tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!
+
+
+
14 April 2016
+
Aurorablade updated:
+
+
Removes the !!FUN!! of having headslugs gold core spawnable.
+
+
Fox McCloud updated:
+
+
Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
+
Added in sound for when airlocks deny access
+
cutting/pulsing wires will play a sound
+
ups nuke ops game mode population requirement from 20 to 30
+
Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
+
Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
+
Mining bots should be less likely to shoot you when attacking hostile mobs
+
Killer tomatoes actually live up to their name now and are hostile mobs
+
Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
+
Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
+
Increased the yield of regular tomatoes by 1
+
Tweak some stats on the killer tomato seeds
+
Fixes the blind player preference not doing anything
+
Adds portaseeder to R&D
+
Scythes will conduct electricity now
+
Mini hoes play a slice sound instead of bludgeon sound
+
Plant analyzer properly has a description and origin tech
+
Can have hulk+dwarf mutations together
+
Can have heat+cold resist together
+
Can only remotely view people who also have remote view
+
Fixes cold mutation not having an overlay
+
Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
+
Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
+
Fixes permanent nearsightedness even when wearing prescription glasses
+
+
KasparoVy updated:
+
+
Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
+
Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
+
+
Meisaka updated:
+
+
law manager no longer freaks out with Malf law
+
+
Tastyfish updated:
+
+
The /vg/ library computer interface has been ported, giving a much better use experience.
+
Books can now be flagged for inappropriate content.
+
+
TheDZD updated:
+
+
Removes shitty Caelcode bees.
+
Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
+
Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
+
Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
+
Added the ability to make Apiaries and Honey frames with wood
+
Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
+
Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
+
Removes some snowflakey mob behavior from bears, snakes and panthers.
+
Hudson is feeling punny.
+
Hostile mob AI should now be a bit more cost-efficient.
+
+
monster860 updated:
+
+
Adds area editing, link mode, and fill mode to the buildmode tool
+
+
+
12 April 2016
+
FalseIncarnate updated:
+
+
Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
+
Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
+
Burnt matches can no longer light cigarettes, pipes, or joints.
+
+
Fethas updated:
+
+
Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
+
You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
+
+
Fox McCloud updated:
+
+
Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
+
Vampires cannot use holoparasites
+
Malf AI will automatically lose if it exits the station z-level
+
+
Tastyfish updated:
+
+
All cats can kill mice now.
+
E-N can't suffocate.
+
Startup time is now shorter.
+
Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
+
+
+
07 April 2016
+
Crazylemon64 updated:
+
+
Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
+
Mulebots will now send announcements to relevant requests consoles on delivery again.
+
+
FalseIncarnate updated:
+
+
Adds logic gates, for doing illogical things in a logical manner.
+
Adds buildable light switches, for all your light toggling needs.
+
Fixes a resource duplication bug with mass driver buttons.
+
+
Fethas updated:
+
+
maybe makes them last longer...maybe..and fixes the event end message
+
+
Fox McCloud updated:
+
+
Maps in the slime management console to Xenobio
+
Reduces Xenobio monkey box count from 4 to 2
+
Fixes weakeyes having a negligible impact
+
Can spawn friendly animals with a new gold core reaction by injection with water
+
Hostile animal spawn increased from 3 to 5 for hostile gold cores
+
Swarmers, revenants, and morphs no longer gold core spawnable
+
Fixes invisible animal spawns from gold core/life reactions
+
Adds tape to the ArtVend
+
Can no longer use sentience potions on bots
+
Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
+
Slimecore reactions now require plasma dust as opposed to dispenser plasma
+
Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
+
Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
+
Epinephrine/plasma reagents changing mutation rate has been removed
+
Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
+
New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
+
Slime glycerol reaction removed
+
Slime cells are now high capacity cells (more power than before)
+
extract enhancer increases the slime core usage by 1 as oppose to setting it to three
+
slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
+
Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
+
Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
+
Processors no longer produce 1 more slime core than intended
+
Less blank/spriteless/empty foods from the silver core reaction
+
Virology mix reactions now use plasma dust as opposed to plasma
+
Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
+
statues are invincible to anything other than full out gibbing.
+
Statues flicker lights spell range increased
+
Blind spell no longer impacts silicons
+
Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
+
Fixes blind spell impacting the statue
+
+
Tastyfish updated:
+
+
Beepsky is no longer a pokemon.
+
pAI-controlled Bots now reliably speak human-understandable languages over the radio.
+
More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
+
+
tigercat2000 updated:
+
+
Items in your off hand will now count towards access.
+
+
+
02 April 2016
+
Crazylemon64 updated:
+
+
Metal foam walls will now produce flooring on space tiles
+
Syringes will now draw water from slime people.
+
+
FalseIncarnate updated:
+
+
Let's you know when your container is full when filling from sinks.
+
Prevents splashing containers onto beakers and buckets that have a lid on them.
+
Pill bottles can now be labeled with a simple pen.
+
Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
+
+
Fethas updated:
+
+
Various spells have had a tweak to stun/reveal/cast, some other number stuff...
+
Nightvision
+
harvest code is now in the abilites file.
+
New fluff objectives
+
Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
+
+
FlattestGuitar updated:
+
+
Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
+
+
Fox McCloud updated:
+
+
Adds in the Lusty Xenomorph Maid Mob; currently admin only.
+
Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
+
removes xenomorph egg from hotel
+
upgrades are no longer needed to for the available toys in the prize vendor
+
Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
+
Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
+
Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
+
Adds disease1 outbreak event
+
Adds appendecitis event
+
Roburgers now properly have nanomachines in them
+
Re-adds nanomachines
+
Experimentor properly generates nanomachines instead of itching powder
+
Fixes big roburgers having a healing reagent in them
+
Adds nanomachines to poison traitor bottles
+
Tajarans can now eat mice, chicks, parrots, and tribbles
+
Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
+
fixes spawned changeling headcrab behavior
+
+
KasparoVy updated:
+
+
Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
+
+
ProperPants updated:
+
+
Maint drones have magboots.
+
Removed plastic from maint drones. Literally useless for station maintenance.
+
Increased starting amounts of some materials for maint drones and engi borgs.
+
Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
+
Operating tables can be deconstructed with a wrench.
+
Fixed and shortened description of metal sheets.
+
+
Tastyfish updated:
+
+
Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
+
MULEbots can now access the engineering destination.
+
All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
+
Diagnostic HUD's now give health and status information about bots.
+
MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
+
Bots should (hopefully) lag the game less now.
+
Beepsky contains 30% more potato.
+
Action progress bars are now smooth.
+
Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
+
Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
+
Shuttle ETA countdowns on status displays are now amber.
+
pAI's can now use the PDA chatrooms.
+
Adds treadmills to brig cells, to give the prisoners something productive to do.
+
+
TheDZD updated:
+
+
A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
+
Removes that fucking facehugger from station collision.
+
+
tigercat2000 updated:
+
+
Virus2 has been removed.
+
Virus1 is back. Viva la revolution.
+
You can now have up to 20 characters.
+
+
+
26 March 2016
+
Fox McCloud updated:
+
+
Adds in dental implant surgery. Implant pills into people's teeth.
+
Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
+
Robotics now has a "sterile" surgical area for performing augmentations
+
Adds the FixOVein and Bone Gel to the autolathe
+
ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
+
+
KasparoVy updated:
+
+
Slime People can now wear underwear.
+
Slime People can now wear undershirts.
+
+
TheDZD updated:
+
+
NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
+
After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
+
+
+
25 March 2016
+
Crazylemon64 updated:
+
+
You now will actually have the correct `real_name` on your DNA.
+
No more roundstart runtimes regarding IPC hair.
+
Mitocholide rejuv will work more usefully now.
+
Limbs and cyborg modules will no longer appear in your screen.
+
Cyborg module icons are now persistent throughout logging in and out.
+
Various cyborg modules, like engineering, now use the proper icon.
+
+
FlattestGuitar updated:
+
+
Adds confetti grenades.
+
+
Fox McCloud updated:
+
+
Fixes Sleeping Carp combos not having an attack animation
+
Fixes several chems not properly healing brute/burn damage, consistently, as intended
+
+
KasparoVy updated:
+
+
Unbranded heads and groins no longer invisible.
+
Zeng-hu left leg will now be in line with the body when facing south.
+
+
+
22 March 2016
+
Crazylemon64 updated:
+
+
Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
+
Makes heads keep hair on removal
+
Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
+
Wounds will vanish on their own now
+
Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
+
Fixes a runtime regarding failing a limb reconnection surgery
+
Copying a client's preferences now overrides the previous mob's DNA
+
A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
+
DNA-lacking species can no longer be DNA-injected
+
Brains are now labeled again
+
Splashing mitocholide on dead organs will make them live again.
+
The body scanner now detects necrotic limbs and organs.
+
pAIs and Drones are now affected by EMPs and explosions while held.
+
+
Fethas updated:
+
+
Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
+
fixes a dumb error in internal bleeeding surgerys
+
Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
+
+
FlattestGuitar updated:
+
+
Adds a snow, navy and desert military jacket.
+
+
Fox McCloud updated:
+
+
Removes random 1% chance to heal fire damage
+
Removes passive healing from resist heat mutation
+
Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
+
Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
+
Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
+
Changes Outpost Mass Driver to prevent accidental spacings
+
Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
+
Shadowlings no longer get hungry or fat and no longer dust on death
+
+
KasparoVy updated:
+
+
The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
+
Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
+
Faux-eye optics for non-Morpheus heads.
+
The ability to change optic (eye) colour if you've got a non-Morpheus head.
+
The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
+
Two hair styles from Polaris.
+
The ability for IPCs to wear undergarments (shirts and trousers).
+
Antennae (colourable) for IPCs.
+
IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
+
Combat/SWAT boots can now be toecut and jacksandals can't.
+
ASAP fix to what would've broken the ability to configure prostheses in character creation.
+
Adjusted masks no longer block CPR (including bandanas).
+
You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
+
+
Regens updated:
+
+
Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
+
Assisted organs will now also take damage from EMP's
+
Internal robotic and assisted organs will now actually take damage from EMP's
+
+
Tastyfish updated:
+
+
Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
+
You can now set the PDA messenger to automatically scroll down to new messages.
+
Pet collars now act as death alarms and can have ID's attached to them.
+
All domestic animals can now wear collars.
+
You can now make video cameras at the autolathe.
+
+
TheDZD updated:
+
+
Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
+
+
TravellingMerchant updated:
+
+
Kidan have new sprites!
+
+
tigercat2000 updated:
+
+
Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
+
Lighting overlays can no longer go below 0 lum_r/g/b
+
Shuttles will work with lighting better.
+
Wizards can no longer teleport to prohibited areas such as Central Command.
+
+
+
16 March 2016
+
Crazylemon64 updated:
+
+
Being in godmode now makes you immune to bombs
+
Science members now get compensated when they ship tech disks to centcomm.
+
Science crew are no longer paid when they "max" research.
+
Roboticists now get credit for making RIPLEYs and Firefighters
+
Slime people can now regrow limbs on a more lax nutrition requirement
+
Enhances the nutripump+ to let slime people regrow limbs with it active
+
Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
+
Rejuvenating a slime person will no longer clog up their "blood"
+
Slime people will now regenerate "blood" from having water in their system
+
The decloner can now be created again
+
Environment smashing mobs can now destroy girders.
+
+
DaveTheHeadcrab updated:
+
+
Removes the check for species on the update_markings proc.
+
+
FalseIncarnate updated:
+
+
Xeno-botany is now more user-friendly, and less random letters/numbers.
+
Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
+
You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
+
+
Fethas updated:
+
+
Syringes are no longer sharp
+
byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
+
fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
+
nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
+
Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
+
Hopefully fixes issues with diona eyes
+
Though shalt not eat robotic organs..including cybernetic implants..
+
ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
+
+
FlattestGuitar updated:
+
+
Adds three new synthanol drinks
+
Drinking synthanol is now a bad idea if you're organic
+
A glass of holy water now looks like normal water
+
+
Fox McCloud updated:
+
+
Adds in drink fizzing sound
+
Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
+
Adds in a fuse burning sound
+
Bath salts, black powder, saltpetre, and charcoal use this sound now
+
Adds in a matchstrike+burning sound
+
Lighting a match triggers this new sound
+
Adds in scissors cutting sound
+
Cutting someone's hair uses this new sound
+
Adds in printer sounds
+
printing off papers from various devices typically uses these sounds
+
Adds computer ambience sounds
+
black box recorder and R&D core servers both play this sound at random rare intervals
+
Reduces the tech level (and requirement) for nanopaste
+
Reduces the tech level (and requirement) for the plasma pistol
+
Removes Nymph and drone tech levels
+
Reduces tech levels on the flora board
+
Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
+
Increases tech cost of the decloner
+
Removes the pacman generators
+
Removes emitter
+
Removes flora machine (functionless anyway)
+
Removes the pre-spawned nanopaste
+
Removes space suits
+
Removes excavation gear
+
Replaces the soil with actual hydroponic trays (more aesthetic than anything)
+
Removes most external asteroid access from the station
+
Excavation storage is now generic science storage
+
removed the plasma sheet
+
Fixes augments not showing up in R&D unless specifically searched for
+
Fixes some augments being unavailable in mech fabs
+
Fixes augments having no construction time
+
Fixes xenos not gaining plasma when breathing in plasma
+
Fixes plasma reagent not generating plasma for a person
+
Screaming has different sounds based on being male or female
+
Implements Goon's screaming sounds.
+
Screaming tone is now based on age of character instead of being random
+
Ups the cooldown on screaming from 2 seconds to 5 seconds
+
Removes chance for Whilhelm scream
+
Borgs can now scream
+
Monkey's now have a unique screaming sound
+
IPCs now scream like cyborgs
+
Updates slot machines to have higher jackpots and more payouts with more interesting sounds
+
Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
+
tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
+
Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
+
Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
+
Chemist warddrobe now has two gas masks
+
Teslium will now impact synthetics AND organics
+
Fixes facehuggers hugging already infected people
+
Fixes facehuggers hugging people while dead
+
Fixes Embryo's developing twice as fast as they should
+
Fixes up some behaviors with xeno eggs
+
Xeno acid can now melt through floors and the asteroid
+
Xeno's now play the gib sound when actually gibbed
+
Implements Changeling headcrabs/headspiders
+
Fixes xenos not throwing their organs when gibbed
+
Fixes swallowed mobs not being ejected when a human is gibbed
+
Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
+
Fixes EMPs causing eye implant users to be permanently blind
+
Increases bag of holding's storage capacity
+
Removing a heart no longer kills the patient instantly, but induces a heart attack
+
Demon hearts will not work
+
Should now actually be able to re-insert hearts
+
Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
+
changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
+
sleepers help you recover from addiction faster
+
Can now make cable coils in autolathes
+
Fixes the slot machine announcements not displaying properly
+
+
Tastyfish updated:
+
+
The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
+
Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
+
Cloning a vampire no longer makes them lose their abilities.
+
Vampires can no longer hypnotize chaplains.
+
Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
+
Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
+
Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
+
+
monster860 updated:
+
+
Mining station now has a podbay.
+
Ore scooping module for the spacepod.
+
Three mining lasers for spacepod: Basic, normal, and burst.
+
Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
+
+
taukausanake updated:
+
+
Mice can now be picked up like diona
+
+
+
08 March 2016
+
Crazylemon64 updated:
+
+
Slime people are now more vulnerable to low temperatures.
+
Slime people are able to slowly regrow limbs at a high nutrition cost.
+
Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
+
Slime people's cores are more vulnerable to damage
+
Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
+
+
Fethas updated:
+
+
the nest buckle now looks for the right organ path
+
Fixed some sprites.
+
No more putting no drops in rechargers,
+
+
Fox McCloud updated:
+
+
Implement's goon's gibbing sound
+
Implement's goon's gibbing sound for robots/silicons
+
Removes old gibbing sound
+
+
Spacemanspark updated:
+
+
Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
+
+
Tastyfish updated:
+
+
Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
+
There are also permanent invisible walls and silent floors that can be made from tranquillite.
+
The Recitence mech is now buildable!
+
The Recitence mech is now playable!
+
Mid-round selection for various creatures and antagonists now consistently asks permission.
+
+
TheDZD updated:
+
+
Adds justice helmets with flashing lights and annoying sirens.
+
Adds crates containing said helmets.
+
Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
+
+
monster860 updated:
+
+
Space pod transitions are now fixed.
+
+
+
07 March 2016
+
Crazylemon64 updated:
+
+
People with VAREDIT can now write matrix variables
+
People with VAREDIT can now modify path variables
+
Refactors the variable editor code somewhat.
+
The buildmode area tool now shows reticules of what you've selected.
+
Switching mobs while using the buildmode tool no longer screws up your UI.
+
Refactors buildmode so it's no longer a special-case system.
+
Adds a copy mode to build mode, which lets you duplicate objects.
+
Any mob in buildmode can work at the fastest possible rate.
+
Fixed a problem where the icons of a person would not correctly update when changing gender.
+
One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
+
Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
+
You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
+
Your organs will now match your gender when you are cloned.
+
Skeletons (when a body rots) no longer retain a fleshy torso.
+
Putting people in an active cryotube now produces the message on insertion, rather than release.
+
An EMP'd cloning pod will now display its sprites correctly.
+
+
FalseIncarnate updated:
+
+
Water Balloons can be filled from more sources than just beakers and watertanks.
+
+
Fox McCloud updated:
+
+
Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
+
Noir mode only activates when the glasses are equipped to your actual eyes
+
Noir Glasses mode can be toggled on or off (defaults to off)
+
Mimes can no longer use spells and continue speaking
+
Mime abilities are now spells with proper icons
+
Mime wall now last 30 seconds, up from 5
+
forecfields/invisible walls now block air currents
+
Adds the Sleeping Carp scroll to the uplink for 17 TC
+
Fixes Shadowlings being able to use guns
+
Fixes sleeping carp scroll users being able to use guns
+
Fixes the Experimentor throwing one item at a time
+
Experimentor menu now automatically refreshes after use
+
Lowers surgery times across the board
+
Removes scalpels causing 1 damage on successful surgery
+
Removes random chance to fracture ribs on a successful surgery
+
Mining drills now have an edge
+
+
KasparoVy updated:
+
+
Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
+
You can now adjust breath masks while buckled into beds and chairs.
+
Known issues with adjusted jackets using the wrong sprites.
+
Blueshield coat in hand and item icons.
+
Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
+
+
Tastyfish updated:
+
+
Infrared emitters can now be rotated while already in an assembly via the UI popup.
+
The infrared emitter can no longer be hidden inside of boxes and still work.
+
The beach now has a border and is splashier.
+
Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
+
Gives the Librarian / Jouralist a multicolored pen.
+
Gives the NT Representative a clipboard.
+
The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
+
+
VampyrBytes updated:
+
+
Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
+
Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
+
+
+
26 February 2016
+
FalseIncarnate updated:
+
+
Chocolate can now make you fat, as expected.
+
+
Fox McCloud updated:
+
+
stamina damage now regenerates slightly faster
+
Adds in whetstones for sharpening objects
+
Kitchen vendor starts off with 5 salt+pepper shakers
+
Can now point while lying or buckled
+
Fixes Capulettium Plus not silencing
+
Fixes slurring, stuttering, drugginess, and silences last half of what they should
+
+
KasparoVy updated:
+
+
Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
+
+
Spacemanspark updated:
+
+
Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
+
+
Tastyfish updated:
+
+
Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
+
+
+
24 February 2016
+
Crazylemon64 updated:
+
+
The defib should be more reliable on people who have ghosted
+
The defib will now give a message if the ghost is still haunting about
+
Attacking someone with an accessory will now let you put things on them without having to strip them.
+
Borers will now properly detach upon death of a mob they are controlling
+
Borers can now see their chemical count while in control of a mob
+
Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
+
Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
+
Borers infesting and hiding are now silent.
+
Made borer's chem lists more nicely formatted
+
No more superspeed attacking simplemobs
+
New players now show up properly under the "who" verb when used as an admin
+
Mining drones will now automatically collect sand lying around
+
RIPLEYs can now drill asteroid turfs for sand
+
You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
+
You can now load the fuel generators from an ore box.
+
The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
+
You can now light cigarettes off of burning mobs.
+
Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
+
Miners can now collect ore by walking over it with an ore satchel on.
+
+
FalseIncarnate updated:
+
+
Adds prize tickets as a replacement for physical arcade prizes.
+
Adds a buildable prize counter to exchange tickets for prizes.
+
Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
+
Adds colorful wallets, for that old school arcade pride.
+
Fixes accidental removal of plump helmet biscuit recipe.
+
Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
+
Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
+
+
FlattestGuitar updated:
+
+
Adds IPC alcohol and a few derivative drinks
+
IPCs can now drink and be fed from glasses
+
+
Fox McCloud updated:
+
+
Laser eyes mutation no longer drains nutrition
+
splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
+
nerfs heart attacks so they do less damage
+
Pickpocket gloves now put the item you strip into your hands as opposed to the floor
+
Picketpocket gloves can now silently strip accessories
+
Pickpocket gloves will no longer give a message for messing up a pickpocket
+
+
KasparoVy updated:
+
+
Adjusting masks while they are not on the face will no longer turn off internals.
+
Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
+
Adds the ability to open/close bomber jackets.
+
Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
+
Adds UI button in top left of screen for jacket adjustment.
+
Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
+
Centralizes jacket/coat adjustment handling.
+
All jackets start closed by default.
+
Geneticist duffelbag on-mob sprite (for all species).
+
Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
+
Refactors back-item icon generation.
+
Typo in the description of Santa's sack.
+
Missing punctuation and gender macros in the description of the bag of holding.
+
The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
+
+
PPI updated:
+
+
Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
+
+
Regen1 updated:
+
+
Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
+
+
Spacemanspark updated:
+
+
Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
+
+
Tastyfish updated:
+
+
The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
+
All of the heads now have multicolored pens.
+
EngiVend now has 10 camera assemblies.
+
Borgs can now use vending machines.
+
There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
+
+
pinatacolada updated:
+
+
Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
+
+
ppi updated:
+
+
When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
+
+
+
13 February 2016
+
Crazylemon64 updated:
+
+
Relaxes the check on what atoms you can follow to any movable atom
+
Mages are now more ragin
+
Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
+
+
DaveTheHeadcrab updated:
+
+
Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
+
+
FalseIncarnate updated:
+
+
Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
+
Adds chimichangas. You know you want a deep-fried burrito.
+
+
Fox McCloud updated:
+
+
Updates some spell icons with better/higher quality icons
+
Updates unarmed attacks to allow for more customization
+
Updates martial arts so they factor in specie's attack messages and sounds
+
Re-balances Sleeping Carp fighting style
+
Re-balances Bo Staff
+
Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
+
Fixes Ei Nath generating two brains
+
Ensures the Necromatic Stone generates actual skeletons
+
Can now strip PDA/IDs from Golems
+
Fixes sleeping carp grab not being an instant aggressive grab
+
Fixes an exploit with declaring war on the station
+
+
KasparoVy updated:
+
+
Orange and purple bandanas for all station species.
+
The ability to colour bandanas with a crayon in a washing machine.
+
Refactors the bandana adjustment system.
+
Minor adjustments to Tajaran and Unathi bandana east/west sprites.
+
Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
+
Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
+
Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
+
Greys now use re-positioned smokeables. They no longer smoke out the eyes.
+
+
TheDZD updated:
+
+
Fixes spacepods being able to shoot through walls.
+
Lowers spacepod weapons fire delay.
+
Increases spacepod weapons energy costs.
+
Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
+
Reduces battery costs for spacepod movement.
+
+
+
10 February 2016
+
Crazylemon64 updated:
+
+
The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
+
A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
+
Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
+
Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
+
Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
+
Adds a reagent system for species reacting to specific reagents
+
Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
+
Increases the frequency of the cortical borer event.
+
People with borers cannot commit suicide - this applies to a controlling borer, too.
+
Borers can no longer overdose their hosts.
+
Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
+
A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
+
Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
+
You can now gib butterflies and lizards with a knife
+
Ghosts can now follow mecha
+
You can now access an R&D console by emagging it - it did nothing before.
+
Walls will now properly smooth and show damage.
+
Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
+
+
Fox McCloud updated:
+
+
Fixes not being able to attach IEDs to beartraps
+
Can no longer spamclick someone to death using headslamming on a toilet/urimal
+
Toilet/urinal headslamming now plays a sound
+
Toilet headslamming damage reduced slightly
+
Can now fill open reagent containers in a toilet to receive "toilet water".
+
No more message spam when someone fills a container using a sink
+
Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
+
Washing things will now use progress bars
+
Ensures consuming a single syndicate donk pocket won't get you addicted to meth
+
Kinetic Accelerators and E-bows automatically reload
+
+
Glorken updated:
+
+
Added a Knight Arena for Holodeck.
+
Added red and blue claymore sprites.
+
Changed overrided to overrode when emagging Holodeck computer.
+
+
KasparoVy updated:
+
+
Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
+
Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
+
Warden now gets their own version of the SWAT sechailer in their locker.
+
HOS now gets the appropriate version of the SWAT sechailer in their locker.
+
Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
+
Minor adjustments to Tajaran breath mask up-state sprites.
+
+
PPI updated:
+
+
Adds a reconnect button to the File menu in the client.
+
Adds head patting
+
+
Regen updated:
+
+
Powersink can now drain a lot more power before going boom
+
Buffed the powersinks drain rate
+
Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
+
Admin log warning before the powersink explodes
+
+
Spacemanspark updated:
+
+
Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
+
Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
+
+
Tastyfish updated:
+
+
Species that don't breathe can kill themselves now!
+
Suicide messages are now catered to your species.
+
Shortened the default pill & patch name when using the ChemMaster.
+
The chaplain now has a service radio headset, as Space Jesus intended.
+
+
TheDZD updated:
+
+
When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
+
Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
+
Adminhelps and PM replies from admins appear in a bold bright red color.
+
PM replies from players appear in a dull/dark purple color.
+
Adds admin attack log to players being converted to cult.
+
Adds shadowling thrall jobbans.
+
Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
+
+
+
31 January 2016
+
Crazylemon64 updated:
+
+
Syndicate borgs can now interact with station machinery
+
People with slime people limbs can now *squish
+
Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
+
+
FalseIncarnate updated:
+
+
Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
+
Adds in the Magic Conch Shell, an admin-only shell of power.
+
+
Fox McCloud updated:
+
+
Updates Summon Guns and Magic to include many of the new guns
+
Summon Guns/Magic can no longer be used during Ragin' Mages
+
+
Tastyfish updated:
+
+
The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
+
Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
+
+
pinatacolada updated:
+
+
Adds NanoUI to the operating computer
+
Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
+
+
+
29 January 2016
+
Crazylemon updated:
+
+
The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
+
Matter eater now allows you to eat humans as if you were fat.
+
Eating mobs with an aggressive grab now generates attack logs.
+
+
Crazylemon64 updated:
+
+
For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
+
Ghosts can now see the contents of smartfridges and look at the drone console
+
Humans now only produce one message when shaken while SSD
+
The supermatter no longer will irradiate everyone, everywhere, when it explodes.
+
Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
+
Brains are no longer able to escape their brain by being a sorcerer.
+
Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
+
Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
+
+
FalseIncarnate updated:
+
+
Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
+
+
Fox McCloud updated:
+
+
Fixes mutadone not working with some genetic mutations
+
Fixes banana honk and silencer being alcoholic
+
Fixes Kahlua being non-alcoholic
+
Fixes polonium not metabolizing
+
Fixes being able to receive free unlimited boxes from the Merchandise store
+
Adds in wooden bucklers
+
Re-adds roman shield to the costume vendor
+
Buffs Riot shield damage from 8 to 10
+
Adds in a Skeleton race
+
Tweaks the skeletons colors to be more realistic and to blend in less with the floor
+
Adds in lichdom spell for the wizard
+
Adds in lesser summon guns spell for wizard
+
adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
+
Wizard can purchase the charge spell from the spell book
+
Wizard can purchase a healing staff from the spell book
+
Tweaks and lowers spell costs of utility spells for wizard
+
Re-organizes the spellbook to be better divided into categories and have a better window size
+
Knock now opens+unlocks lockers
+
Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
+
+
KasparoVy updated:
+
+
Navy blue Centcom Officer's beret for use by the Blueshield.
+
Adds the new navy blue beret to the Blueshield's locker.
+
Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
+
Adds TG energy katana back and belt sprite.
+
Bo staff back sprite.
+
Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
+
Cutting open the toes of footwear so species with feet-claws can wear them.
+
Toeless jackboots.
+
Cleans up glovesnipping and lighting a match with a shoe.
+
Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
+
+
Tastyfish updated:
+
+
Cargonia now has its own section in the manifest.
+
+
TheDZD updated:
+
+
Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
+
+
+
24 January 2016
+
KasparoVy updated:
+
+
Fixes markings overlaying underwear.
+
Nude icon in underwear.dmi
+
Fixes Vox robes not using the correct on-mob sprites.
+
Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
+
Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
+
+
Tastyfish updated:
+
+
Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
+
+
+
23 January 2016
+
Fox McCloud updated:
+
+
Removes Vampire HUD
+
moves the Vampire blood counter to a more easy to see location
+
Adds in a Changeling chemical counter display
+
Adds in a Changeling sting counter display
+
Vampire total blood and usable blood will now appear under status
+
Changes vampire blood display to be similar to ling chemical counter
+
Fixes unnecessary toxin damage being dealt on severe bloodloss
+
Fixes human mobs not receiving proper random names
+
Adds in knight armor
+
Grants the chaplain a set of crusader knight armor
+
Adds in cult-resistant ERT paranormal space suit
+
Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
+
Chaplain's closet is now a secure closet
+
Adds in Assault Gear crate to cargo
+
Adds in military assault belt
+
Adds in spaceworthy swat suits
+
tweaks bandolier to hold 2 additional shotgun shells
+
bartender starts off with +2 additional shells
+
Reduces the cost of the space suit crate and doubles its contents
+
Refactors knives so their behavior is more universal
+
Fixes Hulk not properly being removed when your health drops below a threshold
+
Fixes flickering vision in a mining mech
+
+
Tastyfish updated:
+
+
Poly has taken a seminar on the latest trends in engine operations.
+
Player-controller parrots can now hear their headsets.
+
+
Tigerbat2000 updated:
+
+
The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
+
Cultists can once again actually greentext the escape objective.
+
+
+
20 January 2016
+
DarkPyrolord updated:
+
+
Adds in hardsuit sprites for Vulpkanin
+
+
FalseIncarnate updated:
+
+
Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
+
Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
+
+
Fox McCloud updated:
+
+
Fixes brute damage on weapons not knocking people down.
+
Tweaks implant behavior to be more consistent and unified.
+
Lowers the pAI cooldown from 60 seconds to 5 seconds.
+
Raw telecrystal can now be used to charge uplink implants.
Vulpkanin hardsuit helmets with proper flashlight-on sprites.
+
+
Tastyfish updated:
+
+
The ID computer Access Report printout now separates the access list with commas so it's actually readable.
+
The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
+
In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
+
Table flipping uses correct sprites.
+
+
TheDZD updated:
+
+
Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
+
+
+
18 January 2016
+
Crazylemon updated:
+
+
New classes of shapeshifters have been sighted around the NSS Cyberiad...
+
Wizards now can't teleport to other antag spawn points.
+
Removes an extruding pixel from the left-facing IPC glider monitor sprite.
+
Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
+
Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
+
It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
+
+
Dave The Headcrab updated:
+
+
Adds the advanced energy revolver, toggles between taser and laser modes.
+
Removes the detective's revolver from the blueshield's locker.
+
Changes the taser the blueshield starts with into an advanced energy revolver.
+
+
Deanthelis updated:
+
+
Added the ability for the Magnetic Gripper to pick up and place light tiles.
+
+
Fethas updated:
+
+
Readds the hud icon showing up for master and servent
+
adds mindslave datum hud thingy based on TGs gang huds
+
+
Fox McCloud updated:
+
+
Fixes not being able to add/remove Weapon Permit from IDs.
+
Fixes the energy sword being invisible in-hand when turned on.
+
Fixes the telebaton being invisible in-hand when extended.
+
Fixes eye-stabbing not having an attack animation or hitsound.
+
Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
+
Fixes the butcher cleaver sprite being backwards.
+
Fixes the telebaton sprite being missing from the side.
+
Fixes the meat cleaver being invisible in-hand.
+
Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
+
completely overhauls implants to TG's standards.
+
Adds storage implant.
+
Adds microbomb and macrobomb implants.
+
Adds in support for removing implants directly into cases.
+
Removes Bay style explosive implants.
+
Removes compressed matter implants.
+
Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
+
Fixes/cuts down on the lag caused by monkey cubes.
+
+
Jey updated:
+
+
Inflatable walls and door can now be deflated by altclicking them
+
Fixed lag from expanding multiple monkeycubes at once.
+
+
KasparoVy updated:
+
+
Adds blank icons with standardized timings for species tail wagging, used in icon generation.
+
Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
+
Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
+
Tails now appear in ID cards, overlays things correctly.
+
Tails now overlay and are overlaid by things correctly in preview icons.
+
Modifies the positioning of tail icon generation in the ID card preview icon generation file.
+
Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
+
Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
+
If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
+
Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
+
Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
+
Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
+
Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
Adjusts NV science goggles object icon. Removed strange border and centered it.
+
Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
+
+
Kyep updated:
+
+
Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
+
Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
+
+
NTSAM updated:
+
+
Added a rainbow IPC screen.
+
+
PPI updated:
+
+
Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
+
+
Tastyfish updated:
+
+
The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
+
New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
+
Fixed a few maintenance door names to be in parity to the rest of the station.
+
Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
+
+
Tigercat2000 updated:
+
+
You can no longer use the gibber for monkies.
+
Cleaned up gibber.dm styling.
+
The fire alarm now uses NanoUI, with color coded alert levels.
+
Upgraded NanoUI (again), fancy FontAwesome icons.
+
Didn't add any butts. Yet.
+
+
+
13 January 2016
+
Fox McCloud updated:
+
+
Fixes Rezadone not clearing mutated organs.
+
Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
+
Explosions will no longer destroy things underneath turfs until the turf is exposed.
+
fixes a runtime related to revolver spinning.
+
fixes server loading taking an abnormally long time.
+
+
Kyep updated:
+
+
Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
+
+
Tastyfish updated:
+
+
NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
+
+
+
11 January 2016
+
CrAzYPiLoT updated:
+
+
Fixes the footsteps sounds to the fullest.
+
+
Crazylemon updated:
+
+
Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
+
Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
+
Bomb guardians now are more aware of what is primed to explode.
+
Bomb guardian summoners can now defuse their guardian's bombs without harm.
+
Brought RAGIN' MAGES back up to function.
+
+
Dave The Headcrab updated:
+
+
Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
+
+
Fox McCloud updated:
+
+
Re-arranges the armory and changes its contents minorly.
+
Adds in rubbershot ammo boxes.
+
Fixes Mutadone incurring a massive cost on the server.
+
Positronic brains can no longer speak binary.
+
Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
+
IPC's positronic brains start off toggled off.
+
Fixes the supermatter announcement causing massive amounts of server lag.
+
Adds in tradable telecrystals.
+
+
+
08 January 2016
+
Crazylemon updated:
+
+
Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
+
IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
+
Sleepers and Body Scanners will now reliably work when rotated
+
SSD humans should be asleep more reliably now.
+
+
Dave The Headcrab updated:
+
+
Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
+
Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
+
Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
+
Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
+
Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
+
+
FalseIncarnate updated:
+
+
Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
+
Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
+
Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
+
+
Fethas updated:
+
+
Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
+
+
Fox McCloud updated:
+
+
fixes a bug relating to some brute/burn damage being dealt to human mobs.
+
Adds in overloading APCs, causing them to arc electricity to mobs in range.
+
Makes Engineering related APCs overload proof.
+
Implements the timestop spell.
+
Implements new sepia slime reaction which halts time in an AoE.
+
sentience potions no longer can make slimes sentient.
+
Removes Hulk instant stun.
+
Hulk damage increased.
+
Hulk wears off at a lower health threshold.
+
Fixes strange reagent not working on simple animals.
+
Reduces the amount shock damage and bounces for the Tesla engine.
+
Fixes Syndicate Cyborg's LMG being invisible.
+
Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
+
+
KasparoVy updated:
+
+
Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
+
Removed a duplicate of the human balaclava sprite.
+
Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
+
+
Tastyfish updated:
+
+
Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
+
+
Tigercat2000 updated:
+
+
Added 96x96 (3x) res option to icons menu
+
+
+
06 January 2016
+
Certhic updated:
+
+
Corrected some air alarms so that atmos computer can access them
+
Bodyscanner now sees mechanical parts in internal organs
+
+
Crazylemon64 updated:
+
+
Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
+
+
Tastyfish updated:
+
+
Instruments now use NanoUI.
+
Corrected the blueshield mission briefing.
+
+
+
03 January 2016
+
TheDZD updated:
+
+
Ports over changelog system from /tg/station.
+
+
+
+GoonStation 13 Development Team
+
+ Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
+ Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
+
+
+
diff --git a/html/changelog.js b/html/archived_changelog/changelog.js
similarity index 100%
rename from html/changelog.js
rename to html/archived_changelog/changelog.js
diff --git a/html/changelogs/.all_changelog.yml b/html/archived_changelog/changelogs/.all_changelog.yml
similarity index 97%
rename from html/changelogs/.all_changelog.yml
rename to html/archived_changelog/changelogs/.all_changelog.yml
index 07c327faac8..0bd62e7a715 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/archived_changelog/changelogs/.all_changelog.yml
@@ -11811,3 +11811,45 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- tweak: Cult whispering now uses your real name
- bugfix: Fixed the invisible blob zombies
- bugfix: A runtime in blob/factory/run_action
+2020-04-26:
+ Cazdon:
+ - bugfix: Admin Roles no longer appear on manifest.
+ - tweak: Central Command PDA's no longer appear on the messenger list.
+ - bugfix: Potential Convertee's being unable to be converted.
+ Drakeven:
+ - bugfix: Fixed mislabeled traitor and mindslave special role.
+ Ionward:
+ - tweak: Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific
+ fits for soft space suits.
+ - tweak: Vox can now wear soft space suits, such as EVA (Clown and Mime included),
+ NASA Void, and Syndicate suits.
+ - imageadd: Added Vox soft suit sprites.
+ JKnutson101:
+ - tweak: Combined the Rite of Tribute and Rite of Enlightenment into one Rite of
+ Offering.
+ - bugfix: Sacrificing now properly puts victims that have at one point had CKeys
+ into soul stones, or polls dead-chat to do so.
+ Kyep:
+ - tweak: Tweaked Greater Hellhound, added more non-violent options and one unique
+ combat spell.
+ SteelSlayer:
+ - bugfix: Fixes the "List SSDs and AFKs panel" showing everyone as the target of
+ an assassinate objective
+ - bugfix: The global objectives list is now viewable in the MC Globals menu
+ - bugfix: Reverts some terrible changes that are causing some bugs with traitors
+ - bugfix: Fixes AIs with the combat module not being able to hack APCs
+ TDSSS:
+ - rscdel: duplicate mecha definitions
+ - bugfix: blobbernaut vision blur now clears as intended.
+ - bugfix: fixed a bug preventing ticket system from working under some circumstances.
+ VeteranKyl:
+ - bugfix: DNA Samplers now check if the target species has DNA.
+ - bugfix: Fixed the envenomed blob's spore toxin not causing harm.
+ craftxbox:
+ - bugfix: fixed colors not working without regex
+ - bugfix: fixed text panel not loading when an invalid regex is added
+ - rscadd: polyfilled string.prototype.includes
+ moxian:
+ - bugfix: being in a locker no longer interferes with tracking implant tracking
+ - bugfix: locator no longer locates tracking implants on other z levels.
+ - bugfix: fixed singulo being unable to expand when placed next to containment wall
diff --git a/html/changelogs/__CHANGELOG_README.txt b/html/archived_changelog/changelogs/__CHANGELOG_README.txt
similarity index 100%
rename from html/changelogs/__CHANGELOG_README.txt
rename to html/archived_changelog/changelogs/__CHANGELOG_README.txt
diff --git a/html/changelogs/example.yml b/html/archived_changelog/changelogs/example.yml
similarity index 100%
rename from html/changelogs/example.yml
rename to html/archived_changelog/changelogs/example.yml
diff --git a/html/chevron-expand.png b/html/archived_changelog/chevron-expand.png
similarity index 100%
rename from html/chevron-expand.png
rename to html/archived_changelog/chevron-expand.png
diff --git a/html/chevron.png b/html/archived_changelog/chevron.png
similarity index 100%
rename from html/chevron.png
rename to html/archived_changelog/chevron.png
diff --git a/html/cross-circle.png b/html/archived_changelog/cross-circle.png
similarity index 100%
rename from html/cross-circle.png
rename to html/archived_changelog/cross-circle.png
diff --git a/html/hard-hat-exclamation.png b/html/archived_changelog/hard-hat-exclamation.png
similarity index 100%
rename from html/hard-hat-exclamation.png
rename to html/archived_changelog/hard-hat-exclamation.png
diff --git a/html/image-minus.png b/html/archived_changelog/image-minus.png
similarity index 100%
rename from html/image-minus.png
rename to html/archived_changelog/image-minus.png
diff --git a/html/image-plus.png b/html/archived_changelog/image-plus.png
similarity index 100%
rename from html/image-plus.png
rename to html/archived_changelog/image-plus.png
diff --git a/html/music-minus.png b/html/archived_changelog/music-minus.png
similarity index 100%
rename from html/music-minus.png
rename to html/archived_changelog/music-minus.png
diff --git a/html/music-plus.png b/html/archived_changelog/music-plus.png
similarity index 100%
rename from html/music-plus.png
rename to html/archived_changelog/music-plus.png
diff --git a/html/archived_changelog/panels.css b/html/archived_changelog/panels.css
new file mode 100644
index 00000000000..ac44cf54877
--- /dev/null
+++ b/html/archived_changelog/panels.css
@@ -0,0 +1,10 @@
+body {padding:0px;margin:0px;}
+#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;}
+#main {position:relative;top:50px;left:3%;width:96%;text-align:center;z-index:0;}
+#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";}
+tr.norm {background-color:#f4f4f4;}
+tr.title {background-color:#ccc;}
+tr.alt {background-color:#e7e7e7;}
+.small {font-size:80%;}
+a {text-decoration:none;color:#a0a;}
+a:hover {color:#d3d;}
diff --git a/html/archived_changelog/search.js b/html/archived_changelog/search.js
new file mode 100644
index 00000000000..abc47a97573
--- /dev/null
+++ b/html/archived_changelog/search.js
@@ -0,0 +1,33 @@
+function selectTextField(){
+ var filter_text = document.getElementById('filter');
+ filter_text.focus();
+ filter_text.select();
+}
+function updateSearch(){
+ var input_form = document.getElementById('filter');
+ var filter = input_form.value.toLowerCase();
+ input_form.value = filter;
+ var table = document.getElementById('searchable');
+ var alt_style = 'norm';
+ for(var i = 0; i < table.rows.length; i++){
+ try{
+ var row = table.rows[i];
+ if(row.className == 'title') continue;
+ var found=0;
+ for(var j = 0; j < row.cells.length; j++){
+ var cell = row.cells[j];
+ if(cell.innerText.toLowerCase().indexOf(filter) != -1){
+ found=1;
+ break;
+ }
+ }
+ if(found == 0) row.style.display='none';
+ else{
+ row.style.display='block';
+ row.className = alt_style;
+ if(alt_style == 'alt') alt_style = 'norm';
+ else alt_style = 'alt';
+ }
+ }catch(err) { }
+ }
+}
\ No newline at end of file
diff --git a/html/spell-check.png b/html/archived_changelog/spell-check.png
similarity index 100%
rename from html/spell-check.png
rename to html/archived_changelog/spell-check.png
diff --git a/html/templates/footer.html b/html/archived_changelog/templates/footer.html
similarity index 100%
rename from html/templates/footer.html
rename to html/archived_changelog/templates/footer.html
diff --git a/html/templates/header.html b/html/archived_changelog/templates/header.html
similarity index 100%
rename from html/templates/header.html
rename to html/archived_changelog/templates/header.html
diff --git a/html/tick-circle.png b/html/archived_changelog/tick-circle.png
similarity index 100%
rename from html/tick-circle.png
rename to html/archived_changelog/tick-circle.png
diff --git a/html/wrench-screwdriver.png b/html/archived_changelog/wrench-screwdriver.png
similarity index 100%
rename from html/wrench-screwdriver.png
rename to html/archived_changelog/wrench-screwdriver.png
diff --git a/html/browser/marked-paradise.js b/html/browser/marked-paradise.js
new file mode 100644
index 00000000000..03519139409
--- /dev/null
+++ b/html/browser/marked-paradise.js
@@ -0,0 +1,27 @@
+// Paradise-specific handling of marked.js.
+// Basically we call it on element with id=markdown, and play with paragraphization a bit
+// Requires marked.js to be loaded in order to be useful.
+
+var $ = document.querySelector.bind(document);
+function parse(node) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ parse(node.childNodes[i]);
+ }
+
+ if (!node.innerHTML) {
+ return;
+ }
+
+ node.innerHTML = marked(node.innerHTML.replace(/ /gi, '\n').replace(/\t/gi, ''), { breaks: false, gfm: false })
+ // marked.js wraps content into